├── .clang-format ├── .github ├── FUNDING.yml └── workflows │ └── all.yml ├── .gitignore ├── LICENSE ├── README.md ├── bench.py ├── main ├── miniwasm.c ├── wasm2wasm.c ├── wasm2wat.c ├── wat2wasm.c └── wat2wat.c ├── makefile ├── res ├── binary-trees.png ├── coremark.png ├── fannkuch-redux.png ├── fib_f32.png ├── fib_f64.png ├── fib_i32.png ├── fib_i64.png ├── mandelbrot-simd.png ├── mandelbrot.png ├── nbody.png ├── nop.png └── trap.png ├── results.txt ├── src ├── api │ ├── api.h │ └── wasi.c ├── ast.c ├── ast.h ├── config.h ├── dep │ └── simde │ │ ├── align.h │ │ ├── arch.h │ │ ├── check.h │ │ ├── clang.h │ │ ├── common.h │ │ ├── constify.h │ │ ├── diag.h │ │ ├── features.h │ │ ├── hedley.h │ │ ├── math.h │ │ ├── simd128.h │ │ └── trap.h ├── interp │ ├── interp.c │ ├── interp.h │ ├── interp0.inc │ ├── interp1.inc │ ├── interp2.inc │ └── interp_simd.inc ├── io.c ├── io.h ├── lib.c ├── lib.h ├── opt │ ├── tee.c │ ├── tee.h │ ├── tree.c │ └── tree.h ├── read_bin.c ├── read_bin.h ├── read_wat.c ├── read_wat.h ├── tables.c ├── tables.h ├── write_bin.c ├── write_bin.h ├── write_wat.c └── write_wat.h └── test ├── bench ├── .gitignore ├── binary-trees.c ├── coremark.c ├── fannkuch-redux.c ├── fasta.c ├── fib_f32.c ├── fib_f64.c ├── fib_i32.c ├── fib_i64.c ├── mandelbrot-simd.c ├── mandelbrot.c ├── nbody.c ├── nbody.cpp ├── nop.c └── trap.c ├── core ├── address.wast ├── align.wast ├── binary-leb128.wast ├── binary.wast ├── block.wast ├── br.wast ├── br_if.wast ├── br_table.wast ├── bulk.wast ├── call.wast ├── call_indirect.wast ├── comments.wast ├── const.wast ├── conversions.wast ├── custom.wast ├── data.wast ├── elem.wast ├── endianness.wast ├── exports.wast ├── f32.wast ├── f32_bitwise.wast ├── f32_cmp.wast ├── f64.wast ├── f64_bitwise.wast ├── f64_cmp.wast ├── fac.wast ├── float_exprs.wast ├── float_literals.wast ├── float_memory.wast ├── float_misc.wast ├── forward.wast ├── func.wast ├── func_ptrs.wast ├── global.wast ├── i32.wast ├── i64.wast ├── if.wast ├── imports.wast ├── inline-module.wast ├── int_exprs.wast ├── int_literals.wast ├── labels.wast ├── left-to-right.wast ├── linking.wast ├── load.wast ├── local_get.wast ├── local_set.wast ├── local_tee.wast ├── loop.wast ├── memory.wast ├── memory_copy.wast ├── memory_fill.wast ├── memory_grow.wast ├── memory_init.wast ├── memory_redundancy.wast ├── memory_size.wast ├── memory_trap.wast ├── names.wast ├── nop.wast ├── ref_func.wast ├── ref_is_null.wast ├── ref_null.wast ├── return.wast ├── select.wast ├── skip-stack-guard-page.wast ├── stack.wast ├── start.wast ├── store.wast ├── switch.wast ├── table-sub.wast ├── table.wast ├── table_copy.wast ├── table_fill.wast ├── table_get.wast ├── table_grow.wast ├── table_init.wast ├── table_set.wast ├── table_size.wast ├── token.wast ├── tokens.wast ├── traps.wast ├── type.wast ├── unreachable.wast ├── unreached-invalid.wast ├── unreached-valid.wast ├── unwind.wast ├── utf8-custom-section-id.wast ├── utf8-import-field.wast ├── utf8-import-module.wast └── utf8-invalid-encoding.wast ├── crc.c ├── fib.lua ├── hello.c ├── names.wast ├── nest.wast ├── test.c ├── tree.c └── tree.lua /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: Google 4 | IndentWidth: 4 5 | ColumnLimit: 0 -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: ShawSumma 2 | -------------------------------------------------------------------------------- /.github/workflows/all.yml: -------------------------------------------------------------------------------- 1 | name: Builds Web49 2 | on: [push] 3 | jobs: 4 | benchmark: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v3 8 | with: 9 | submodules: true 10 | - uses: mymindstorm/setup-emsdk@v11 11 | with: 12 | version: 3.1.25 13 | actions-cache-folder: 'emsdk-cache' 14 | - run: make CC=gcc OPT='-O3 -flto -fomit-frame-pointer' all CFLAGS+='-DWEB49_OPT_CONST0' 15 | - run: sudo cp bin/miniwasm /usr/bin/miniwasm 16 | - run: pushd ./; git clone https://github.com/wasm3/wasm3 && cd wasm3 && cmake . && sudo make -Bj install; popd 17 | - run: sudo apt install -y python3 python3-pip 18 | - run: pip3 install matplotlib 19 | - run: python3 bench.py 20 | timeout-minutes: 3 21 | - uses: actions/upload-artifact@v3 22 | with: 23 | name: benchmarks 24 | path: | 25 | test/bench/fannkuch-redux.png 26 | test/bench/mandelbrot.png 27 | test/bench/binary-trees.png 28 | test/bench/nop.png 29 | test/bench/fib_f32.png 30 | test/bench/fib_f64.png 31 | test/bench/fib_i32.png 32 | test/bench/fib_i64.png 33 | test/bench/mandelbrot-simd.png 34 | test/bench/fasta.png 35 | test/bench/nbody.png 36 | test/bench/trap.png 37 | test/bench/results.json 38 | web49-windows-release: 39 | runs-on: windows-latest 40 | steps: 41 | - uses: actions/checkout@v3 42 | - uses: mymindstorm/setup-emsdk@v11 43 | - run: make -j4 UNAME_S=Windows CC=gcc OPT='-O3 -fomit-frame-pointer' install INSTALL=web49-windows-release 44 | - uses: actions/upload-artifact@v3 45 | with: 46 | name: web49-windows-release 47 | path: web49-windows-release 48 | web49-linux-release: 49 | runs-on: ubuntu-latest 50 | steps: 51 | - uses: actions/checkout@v3 52 | with: 53 | submodules: true 54 | - run: sudo apt install --fix-missing libgl1-mesa-dev libxcursor-dev libxi-dev libxinerama-dev libxrandr-dev emscripten 55 | - run: make -j4 CC=gcc OPT='-O3 -fomit-frame-pointer -flto' install INSTALL=web49-linux-release 56 | - uses: actions/upload-artifact@v3 57 | with: 58 | name: web49-linux-release 59 | path: web49-linux-release 60 | web49-linux-debug: 61 | runs-on: ubuntu-latest 62 | steps: 63 | - uses: actions/checkout@v3 64 | with: 65 | submodules: true 66 | - run: sudo apt install --fix-missing libgl1-mesa-dev libxcursor-dev libxi-dev libxinerama-dev libxrandr-dev emscripten 67 | - run: make -j4 CC=cc OPT='-g3' CFLAGS='-Wall -Wextra -Werror -Wno-unused-parameter' install INSTALL=web49-linux-debug 68 | - uses: actions/upload-artifact@v3 69 | with: 70 | name: web49-linux-debug 71 | path: web49-linux-debug 72 | macos-web49: 73 | runs-on: macos-latest 74 | steps: 75 | - uses: actions/checkout@v3 76 | with: 77 | submodules: true 78 | - run: brew install emscripten 79 | - run: make -j4 CC=clang UNAME_S=Darwin OPT='-O3 -fomit-frame-pointer -flto' install INSTALL=web49-mac-release 80 | - uses: actions/upload-artifact@v3 81 | with: 82 | name: web49-mac-release 83 | path: web49-mac-release -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode/* 3 | bin/* 4 | err.txt 5 | install 6 | miniwasm 7 | miniwasm.exe 8 | out.* 9 | test/bench/results.json 10 | test/core/* 11 | test/*.wasm 12 | *.core 13 | *.exe 14 | *.exp 15 | *.gcda 16 | *.ilk 17 | *.lib 18 | *.o 19 | *.pdb 20 | *.tmp 21 | *.wasm 22 | *.wat 23 | *.profdata 24 | spec -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Shaw Summa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Web49 2 | 3 | Web49 is a WebAssembly toolkit and interpreter. 4 | 5 | ## Try the first release! [v0.0.1](https://github.com/FastVM/Web49/releases/tag/v0.0.1) 6 | 7 | Web49 contains a few tools for working with WebAssembly. 8 | 9 | * interpreters 10 | * miniwasm 11 | * [fast](#benchmarks) wasm interpreter 12 | * uses technology from [minivm](https://github.com/fastvm/minivm) 13 | * supports multiple wasm formats 14 | * wasm binary format: ~100% complete 15 | * wasm text format: ~95% complete 16 | * wasm spect test: ~75% complete 17 | * includes a custom [WASI](https://github.com/webassembly/wasi) [implementation](src/api/wasi.c) 18 | * raywasm 19 | * wasm interpreter based on miniwasm 20 | * wasm binary tools rewrite 21 | * much simpler than WABT's tools 22 | * much smaller than Binaryen's tools 23 | * [wat2wasm](main/wat2wasm.c) 24 | * convert wasm text into wasm binary 25 | * [wasm2wat](main/wasm2wat.c) 26 | * generates nearly identical wat as binaryen or wabt 27 | * turn wasm binary into wasm text 28 | * supports all of wasm 1.0 and some extensions 29 | * [wasm2wasm](main/wasm2wasm.c) 30 | * shrink numbers in wasm files generated by llvm 31 | * saves 0-4 bytes per 32 bit number 32 | * saves 0-10 bytes per 64 bit number 33 | * round trip parse and reemit 34 | 35 | ## Benchmarks 36 | 37 | Benchmarks performed by [wasm3](https://github.com/wasm3/wasm3) and Web49's miniwasm. Ran on an 2020 Macbook Air (M1 + 8GiB ram) using [bench.py](bench.py). 38 | 39 | All Benchmarks compiled with: `emcc -O2` 40 | 41 | One can also view results run on [github actions](https://github.com/FastVM/Web49/actions) 42 | One can run the benchmarks for themselves. 43 | 44 | * python3 45 | * with pip 46 | * emcc 47 | * wasm3 48 | * make 49 | * tested with GNUMake 50 | * works with BSDMake too 51 | * and a C compiler 52 | * gcc/clang/tcc works 53 | * msvc would work if someone rewrites two macros 54 | * #define NEXT() break 55 | * #define LABEL(X) case X: 56 | * probably a couple others 57 | 58 | ```sh 59 | git clone https://github.com/fastvm/web49 60 | cd web49 61 | make CC=gcc # gcc is fastest in my tests 62 | python3 -m pip install matplotlib 63 | python3 bench.py 64 | ``` 65 | 66 | ### [Binary Trees](test/bench/binary-trees.c) 67 | ![](res/binary-trees.png) 68 | 69 | ### [Coremark](test/bench/coremark.c) 70 | ![](res/coremark.png) 71 | 72 | ### [Fannkuch Redux](test/bench/fannkuch-redux.c) 73 | ![](res/fannkuch-redux.png) 74 | 75 | ### [Fibonacci on ints32_t](test/bench/fib_i32.c) 76 | ![](res/fib_i32.png) 77 | 78 | ### [Mandelbrot with SIMD](test/bench/mandelbrot-simd.c) 79 | ![](res/mandelbrot-simd.png) 80 | 81 | ### [Mandelbrot without SIMD](test/bench/mandelbrot.c) 82 | ![](res/mandelbrot.png) 83 | 84 | ### [Nbody](test/bench/nbody.c) 85 | ![](res/nbody.png) 86 | 87 | ### [Executing A Trap](test/bench/trap.c) 88 | ![](res/trap.png) 89 | -------------------------------------------------------------------------------- /bench.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import matplotlib.pyplot as plt 4 | import os 5 | import subprocess 6 | import time 7 | import argparse 8 | import colorsys 9 | import json 10 | 11 | cur = os.path.dirname(os.path.realpath(__file__)) 12 | 13 | os.chdir('test/bench') 14 | 15 | parser = argparse.ArgumentParser( 16 | prog='bench', 17 | description='Benchmark Wasm Engines', 18 | ) 19 | 20 | parser.add_argument('--runs', '-r', type=int, help='number of benchmark runs', default=1) 21 | parser.add_argument('--engine', '-e', type=str, action='append', default=[]) 22 | parser.add_argument('--test', '-t', type=str, action='append', default=[]) 23 | parser.add_argument('--compiler', '-c', type=str, default='emcc') 24 | parser.add_argument('--opt', '-O', type=str, default='2') 25 | 26 | args = parser.parse_args() 27 | 28 | runs = args.runs 29 | engines = args.engine 30 | emcc = args.compiler 31 | optlevel = args.opt 32 | # emccflags = ['-msimd128', '-mmultivalue', '-fno-exceptions'] 33 | emccflags = ['-msimd128'] 34 | emccflags = [] 35 | if len(engines) == 0: 36 | engines = ['wasm3', os.path.join(cur, 'bin/miniwasm')] 37 | engines.extend(['wasmer', 'wasmtime']) 38 | 39 | if len(args.test) == 0: 40 | tests = { 41 | 'trap': { 42 | 'runs': 10, 43 | 'args': [], 44 | 'memory': 256, 45 | }, 46 | 'nop': { 47 | 'runs': 100, 48 | 'args': [], 49 | 'memory': 256, 50 | }, 51 | # 'coremark': { 52 | # 'runs': 1, 53 | # 'args': ['3000'], 54 | # 'memory': 256, 55 | # }, 56 | 'fib_f32': { 57 | 'runs': 1, 58 | 'args': ['40'], 59 | 'memory': 256, 60 | }, 61 | 'fib_i32': { 62 | 'runs': 1, 63 | 'args': ['40'], 64 | 'memory': 256, 65 | }, 66 | 'fib_f64': { 67 | 'runs': 1, 68 | 'args': ['40'], 69 | 'memory': 256, 70 | }, 71 | 'fib_i64': { 72 | 'runs': 1, 73 | 'args': ['40'], 74 | 'memory': 256, 75 | }, 76 | 'binary-trees': { 77 | 'runs': 1, 78 | 'args': ['16'], 79 | 'memory': 2**12, 80 | }, 81 | 'fannkuch-redux': { 82 | 'runs': 1, 83 | 'args': ['10'], 84 | 'memory': 256, 85 | }, 86 | 'mandelbrot-simd': { 87 | 'runs': 1, 88 | 'args': ['2000'], 89 | 'memory': 256, 90 | }, 91 | 'mandelbrot': { 92 | 'runs': 1, 93 | 'args': ['2000'], 94 | 'memory': 256, 95 | }, 96 | 'nbody': { 97 | 'runs': 1, 98 | 'args': ['2000000'], 99 | 'memory': 256, 100 | }, 101 | } 102 | else: 103 | tests = {} 104 | for test in args.test: 105 | [name, *args1] = test.split(':') 106 | split = name.split('+') 107 | if len(split) == 1: 108 | n = 1 109 | else: 110 | name = split[0] 111 | n = int(split[1]) 112 | 113 | tests[name] = { 114 | 'args': args1, 115 | 'runs': n, 116 | 'memory': 256, 117 | } 118 | 119 | obj = {} 120 | testdata = {} 121 | for i in range(1, runs+1): 122 | print('RUN: #' + str(i)) 123 | for test in tests.keys(): 124 | print(' TEST: ' + test) 125 | build = subprocess.call([*emcc.split(' '), *emccflags, '-Xlinker', f'--initial-memory={tests[test]["memory"] * (2 ** 16)}', f"-O{optlevel}", test + '.c', '-o', test + '.wasm']) 126 | if test not in testdata: 127 | testdata[test] = {} 128 | data = testdata[test] 129 | for engine in engines: 130 | print(' ENGINE: ' + engine) 131 | if engine not in data: 132 | data[engine] = [] 133 | times = data[engine] 134 | for i in range(tests[test]['runs']): 135 | start = time.time() 136 | run = subprocess.call([engine, test + '.wasm', *tests[test]['args']], stdout=subprocess.DEVNULL) 137 | end = time.time() 138 | times.append(end - start) 139 | 140 | fig, ax = plt.subplots() 141 | 142 | keys = data.keys() 143 | values = [sum(data[i]) / len(data[i]) for i in keys] 144 | 145 | keys = [key.replace(cur, '.').replace('./bin/', '') for key in keys] 146 | 147 | for i,key in enumerate(keys): 148 | rgb = colorsys.hsv_to_rgb(i / (len(keys) * (5/4)) + 0.25, 0.25, 0.85) 149 | 150 | ax.bar(key, values[i], color=(*rgb, 1.0)) 151 | 152 | ax.set_ylabel('time taken in seconds') 153 | ax.set_xlabel('wasm engine') 154 | 155 | ax.set_title(' '.join([test, *tests[test]['args']])) 156 | fig.savefig(test + '.png') 157 | 158 | obj[test] = {} 159 | for i,key in enumerate(keys): 160 | obj[test][key] = values[i] 161 | 162 | with open('results.json', 'w') as outputfp: 163 | json.dump(obj, outputfp) -------------------------------------------------------------------------------- /main/wasm2wasm.c: -------------------------------------------------------------------------------- 1 | #include "../src/ast.h" 2 | #include "../src/interp/interp.h" 3 | #include "../src/read_bin.h" 4 | #include "../src/write_bin.h" 5 | 6 | static int web49_file_main(const char *inarg, const char *outarg) { 7 | web49_io_input_t infile = web49_io_input_open(inarg); 8 | web49_module_t mod = web49_readbin_module(&infile); 9 | web49_writebin_buf_t buf = {0}; 10 | web49_writebin_module(&buf, mod); 11 | FILE *outfile = fopen(outarg, "wb"); 12 | fwrite(buf.data, 1, buf.len, outfile); 13 | fclose(outfile); 14 | return 0; 15 | } 16 | 17 | int main(int argc, const char **argv) { 18 | const char *inarg = NULL; 19 | const char *outarg = NULL; 20 | for (int i = 1; i < argc; i += 1) { 21 | if (!strcmp(argv[i], "-o")) { 22 | i += 1; 23 | outarg = argv[i]; 24 | } else if (inarg == NULL) { 25 | inarg = argv[i]; 26 | } else { 27 | fprintf(stderr, "extra cli arg: %s\n", argv[i]); 28 | return 1; 29 | } 30 | } 31 | return web49_file_main(inarg, outarg); 32 | } 33 | -------------------------------------------------------------------------------- /main/wasm2wat.c: -------------------------------------------------------------------------------- 1 | #include "../src/ast.h" 2 | #include "../src/read_bin.h" 3 | #include "../src/write_wat.h" 4 | 5 | static int web49_file_main(const char *inarg, const char *outarg) { 6 | web49_io_input_t infile = web49_io_input_open(inarg); 7 | web49_module_t mod = web49_readbin_module(&infile); 8 | web49_io_output_t outfile = {0}; 9 | web49_wat_print_module(&outfile, mod); 10 | if (outarg == NULL) { 11 | fwrite(outfile.byte_buf, 1, outfile.byte_index, stdout); 12 | } else { 13 | web49_file_output_dump(outfile, outarg); 14 | } 15 | return 0; 16 | } 17 | 18 | int main(int argc, const char **argv) { 19 | const char *inarg = NULL; 20 | const char *outarg = NULL; 21 | for (int i = 1; i < argc; i += 1) { 22 | if (!strcmp(argv[i], "-o")) { 23 | i += 1; 24 | outarg = argv[i]; 25 | } else if (inarg == NULL) { 26 | inarg = argv[i]; 27 | } else { 28 | fprintf(stderr, "extra cli arg: %s\n", argv[i]); 29 | return 1; 30 | } 31 | } 32 | return web49_file_main(inarg, outarg); 33 | } 34 | -------------------------------------------------------------------------------- /main/wat2wasm.c: -------------------------------------------------------------------------------- 1 | #include "../src/ast.h" 2 | #include "../src/interp/interp.h" 3 | #include "../src/read_wat.h" 4 | #include "../src/write_bin.h" 5 | 6 | static int web49_file_main(const char *inarg, const char *outarg) { 7 | web49_io_input_t infile = web49_io_input_open(inarg); 8 | web49_module_t mod = web49_readwat_module(&infile); 9 | web49_writebin_buf_t buf = {0}; 10 | web49_writebin_module(&buf, mod); 11 | FILE *outfile = fopen(outarg, "wb"); 12 | fwrite(buf.data, 1, buf.len, outfile); 13 | fclose(outfile); 14 | return 0; 15 | } 16 | 17 | int main(int argc, const char **argv) { 18 | const char *inarg = NULL; 19 | const char *outarg = NULL; 20 | for (int i = 1; i < argc; i += 1) { 21 | if (!strcmp(argv[i], "-o")) { 22 | i += 1; 23 | outarg = argv[i]; 24 | } else if (inarg == NULL) { 25 | inarg = argv[i]; 26 | } else { 27 | fprintf(stderr, "extra cli arg: %s\n", argv[i]); 28 | return 1; 29 | } 30 | } 31 | return web49_file_main(inarg, outarg); 32 | } 33 | -------------------------------------------------------------------------------- /main/wat2wat.c: -------------------------------------------------------------------------------- 1 | #include "../src/ast.h" 2 | #include "../src/read_wat.h" 3 | #include "../src/write_wat.h" 4 | 5 | static int web49_file_main(const char *inarg, const char *outarg) { 6 | web49_io_input_t infile = web49_io_input_open(inarg); 7 | web49_module_t mod = web49_readwat_module(&infile); 8 | web49_io_output_t outfile = {0}; 9 | web49_wat_print_module(&outfile, mod); 10 | if (outarg == NULL) { 11 | fwrite(outfile.byte_buf, 1, outfile.byte_index, stdout); 12 | } else { 13 | web49_file_output_dump(outfile, outarg); 14 | } 15 | return 0; 16 | } 17 | 18 | int main(int argc, const char **argv) { 19 | const char *inarg = NULL; 20 | const char *outarg = NULL; 21 | for (int i = 1; i < argc; i += 1) { 22 | if (!strcmp(argv[i], "-o")) { 23 | i += 1; 24 | outarg = argv[i]; 25 | } else if (inarg == NULL) { 26 | inarg = argv[i]; 27 | } else { 28 | fprintf(stderr, "extra cli arg: %s\n", argv[i]); 29 | return 1; 30 | } 31 | } 32 | return web49_file_main(inarg, outarg); 33 | } 34 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | 2 | PYTHON ?= python3 3 | OPT ?= -O2 4 | 5 | INSTALL ?= install 6 | 7 | EMCC ?= emcc 8 | 9 | PROG_SRCS := main/wat2wat.c main/wasm2wat.c main/wat2wasm.c main/wasm2wasm.c main/miniwasm.c main/raywasm.c main/runtime/rlruntime.c 10 | PROG_OBJS := $(PROG_SRCS:%.c=%.o) 11 | 12 | WEB49_SRCS := src/lib.c src/read_bin.c src/read_wat.c src/write_wat.c src/write_bin.c src/io.c src/tables.c src/interp/interp.c src/opt/tree.c src/opt/tee.c src/ast.c src/api/wasi.c 13 | WEB49_OBJS := $(WEB49_SRCS:%.c=%.o) 14 | 15 | OBJS := $(WEB49_OBJS) 16 | 17 | UNAME_S_CMD != uname -s 18 | 19 | UNAME_S ?= $(UNAME_S_CMD) 20 | 21 | RGLFW_M_OR_C_Windows = c 22 | RGLFW_M_OR_C_FreeBSD = c 23 | RGLFW_M_OR_C_Linux = c 24 | RGLFW_M_OR_C_Darwin = m 25 | 26 | TEST_PREFIX = test/core 27 | 28 | TEST_FILES != find $(TEST_PREFIX) -name '*.wast' 29 | TEST_OUTPUTS = $(TEST_FILES:%.wast=%.txt) 30 | 31 | default: all 32 | 33 | all: bins 34 | 35 | # install web49 36 | 37 | install: bins 38 | cp bin/miniwasm $(INSTALL) 39 | chmod $(INSTALL)/miniwasm 40 | 41 | # tests 42 | 43 | test: results.txt 44 | 45 | results.txt: $(TEST_OUTPUTS) 46 | @cat /dev/null $(TEST_OUTPUTS) | sort > results.txt 47 | 48 | $(TEST_OUTPUTS): bin/miniwasm $(@:%.txt=%.wast) | $(TEST_PREFIX) 49 | @./bin/miniwasm $(@:%.txt=%.wast) 2>$(@:%.txt=%.log); \ 50 | if test $$? -eq 0; \ 51 | then mv $(@:%.txt=%.log) $(@:%.txt=%.pass.log) && echo "PASS $(@:$(TEST_PREFIX)/%.txt=%)" > $(@); \ 52 | else mv $(@:%.txt=%.log) $(@:%.txt=%.fail.log) && echo "FAIL $(@:$(TEST_PREFIX)/%.txt=%)" > $(@); \ 53 | fi 54 | 55 | # test/wasi: 56 | # test -d wasi-testsuite || git clone https://github.com/WebAssembly/wasi-testsuite spec --depth 1 57 | # rm -fr test/wasi 58 | 59 | test/core: 60 | test -d spec || git clone https://github.com/WebAssembly/spec/ spec --depth 1 61 | rm -fr test/core 62 | cp -r spec/test/core test/core 63 | rm -r test/core/simd/meta 64 | 65 | # bin 66 | 67 | bins: bin/wasm2wat bin/wat2wasm bin/wasm2wasm bin/wat2wat bin/miniwasm 68 | 69 | bin/miniwasm: main/miniwasm.o $(OBJS) 70 | @mkdir -p bin 71 | $(CC) $(OPT) main/miniwasm.o $(OBJS) -o $(@) -lm $(LDFLAGS) 72 | 73 | bin/wat2wasm: main/wat2wasm.o $(OBJS) 74 | @mkdir -p bin 75 | $(CC) $(OPT) main/wat2wasm.o $(OBJS) -o $(@) -lm $(LDFLAGS) 76 | 77 | bin/wasm2wat: main/wasm2wat.o $(OBJS) 78 | @mkdir -p bin 79 | $(CC) $(OPT) main/wasm2wat.o $(OBJS) -o $(@) -lm $(LDFLAGS) 80 | 81 | bin/wasm2wasm: main/wasm2wasm.o $(OBJS) 82 | @mkdir -p bin 83 | $(CC) $(OPT) main/wasm2wasm.o $(OBJS) -o $(@) -lm $(LDFLAGS) 84 | 85 | bin/wat2wat: main/wat2wat.o $(OBJS) 86 | @mkdir -p bin 87 | $(CC) $(OPT) main/wat2wat.o $(OBJS) -o $(@) -lm $(LDFLAGS) 88 | 89 | # util 90 | 91 | format: .dummy 92 | find src main -name '*.c' | xargs -I FILENAME clang-format -style=file -i FILENAME 93 | find src main -name '*.h' | xargs -I FILENAME clang-format -style=file -i FILENAME 94 | find src main -name '*.inc' | xargs -I FILENAME clang-format -style=file -i FILENAME 95 | 96 | clean: .dummy 97 | find src main -name '*.o' | xargs rm 98 | find bin -type f | xargs rm 99 | find test/core -name '*.txt' | xargs rm 100 | find test/core -name '*.log' | xargs rm 101 | 102 | # intermediate files 103 | 104 | $(PROG_OBJS) $(WEB49_OBJS): $(@:%.o=%.c) 105 | $(CC) -c $(OPT) $(@:%.o=%.c) -o $(@) $(CFLAGS) 106 | 107 | # dummy 108 | 109 | .dummy: 110 | -------------------------------------------------------------------------------- /res/binary-trees.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastVM/Web49/0a8b8a629b16fd71698287d0e40a0341db2ef39a/res/binary-trees.png -------------------------------------------------------------------------------- /res/coremark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastVM/Web49/0a8b8a629b16fd71698287d0e40a0341db2ef39a/res/coremark.png -------------------------------------------------------------------------------- /res/fannkuch-redux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastVM/Web49/0a8b8a629b16fd71698287d0e40a0341db2ef39a/res/fannkuch-redux.png -------------------------------------------------------------------------------- /res/fib_f32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastVM/Web49/0a8b8a629b16fd71698287d0e40a0341db2ef39a/res/fib_f32.png -------------------------------------------------------------------------------- /res/fib_f64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastVM/Web49/0a8b8a629b16fd71698287d0e40a0341db2ef39a/res/fib_f64.png -------------------------------------------------------------------------------- /res/fib_i32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastVM/Web49/0a8b8a629b16fd71698287d0e40a0341db2ef39a/res/fib_i32.png -------------------------------------------------------------------------------- /res/fib_i64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastVM/Web49/0a8b8a629b16fd71698287d0e40a0341db2ef39a/res/fib_i64.png -------------------------------------------------------------------------------- /res/mandelbrot-simd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastVM/Web49/0a8b8a629b16fd71698287d0e40a0341db2ef39a/res/mandelbrot-simd.png -------------------------------------------------------------------------------- /res/mandelbrot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastVM/Web49/0a8b8a629b16fd71698287d0e40a0341db2ef39a/res/mandelbrot.png -------------------------------------------------------------------------------- /res/nbody.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastVM/Web49/0a8b8a629b16fd71698287d0e40a0341db2ef39a/res/nbody.png -------------------------------------------------------------------------------- /res/nop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastVM/Web49/0a8b8a629b16fd71698287d0e40a0341db2ef39a/res/nop.png -------------------------------------------------------------------------------- /res/trap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastVM/Web49/0a8b8a629b16fd71698287d0e40a0341db2ef39a/res/trap.png -------------------------------------------------------------------------------- /results.txt: -------------------------------------------------------------------------------- 1 | FAIL binary 2 | FAIL binary-leb128 3 | FAIL br_table 4 | FAIL bulk 5 | FAIL call_indirect 6 | FAIL comments 7 | FAIL conversions 8 | FAIL custom 9 | FAIL data 10 | FAIL elem 11 | FAIL exports 12 | FAIL float_exprs 13 | FAIL float_literals 14 | FAIL float_memory 15 | FAIL func_ptrs 16 | FAIL global 17 | FAIL imports 18 | FAIL inline-module 19 | FAIL linking 20 | FAIL memory 21 | FAIL memory_copy 22 | FAIL memory_fill 23 | FAIL memory_grow 24 | FAIL memory_init 25 | FAIL memory_redundancy 26 | FAIL memory_size 27 | FAIL memory_trap 28 | FAIL names 29 | FAIL ref_func 30 | FAIL ref_is_null 31 | FAIL ref_null 32 | FAIL select 33 | FAIL simd/simd_address 34 | FAIL simd/simd_align 35 | FAIL simd/simd_bit_shift 36 | FAIL simd/simd_bitwise 37 | FAIL simd/simd_boolean 38 | FAIL simd/simd_const 39 | FAIL simd/simd_conversions 40 | FAIL simd/simd_f32x4 41 | FAIL simd/simd_f32x4_arith 42 | FAIL simd/simd_f32x4_cmp 43 | FAIL simd/simd_f32x4_pmin_pmax 44 | FAIL simd/simd_f32x4_rounding 45 | FAIL simd/simd_f64x2 46 | FAIL simd/simd_f64x2_arith 47 | FAIL simd/simd_f64x2_cmp 48 | FAIL simd/simd_f64x2_pmin_pmax 49 | FAIL simd/simd_f64x2_rounding 50 | FAIL simd/simd_i16x8_arith 51 | FAIL simd/simd_i16x8_arith2 52 | FAIL simd/simd_i16x8_cmp 53 | FAIL simd/simd_i16x8_extadd_pairwise_i8x16 54 | FAIL simd/simd_i16x8_extmul_i8x16 55 | FAIL simd/simd_i16x8_q15mulr_sat_s 56 | FAIL simd/simd_i16x8_sat_arith 57 | FAIL simd/simd_i32x4_arith 58 | FAIL simd/simd_i32x4_arith2 59 | FAIL simd/simd_i32x4_cmp 60 | FAIL simd/simd_i32x4_dot_i16x8 61 | FAIL simd/simd_i32x4_extadd_pairwise_i16x8 62 | FAIL simd/simd_i32x4_extmul_i16x8 63 | FAIL simd/simd_i32x4_trunc_sat_f32x4 64 | FAIL simd/simd_i32x4_trunc_sat_f64x2 65 | FAIL simd/simd_i64x2_arith 66 | FAIL simd/simd_i64x2_arith2 67 | FAIL simd/simd_i64x2_cmp 68 | FAIL simd/simd_i64x2_extmul_i32x4 69 | FAIL simd/simd_i8x16_arith 70 | FAIL simd/simd_i8x16_arith2 71 | FAIL simd/simd_i8x16_cmp 72 | FAIL simd/simd_i8x16_sat_arith 73 | FAIL simd/simd_int_to_int_extend 74 | FAIL simd/simd_lane 75 | FAIL simd/simd_linking 76 | FAIL simd/simd_load 77 | FAIL simd/simd_load16_lane 78 | FAIL simd/simd_load32_lane 79 | FAIL simd/simd_load64_lane 80 | FAIL simd/simd_load8_lane 81 | FAIL simd/simd_load_extend 82 | FAIL simd/simd_load_splat 83 | FAIL simd/simd_load_zero 84 | FAIL simd/simd_splat 85 | FAIL simd/simd_store 86 | FAIL simd/simd_store16_lane 87 | FAIL simd/simd_store32_lane 88 | FAIL simd/simd_store64_lane 89 | FAIL simd/simd_store8_lane 90 | FAIL stack 91 | FAIL start 92 | FAIL table 93 | FAIL table-sub 94 | FAIL table_copy 95 | FAIL table_fill 96 | FAIL table_get 97 | FAIL table_grow 98 | FAIL table_init 99 | FAIL table_set 100 | FAIL table_size 101 | FAIL token 102 | FAIL tokens 103 | FAIL unreached-invalid 104 | FAIL utf8-custom-section-id 105 | FAIL utf8-import-field 106 | FAIL utf8-import-module 107 | FAIL utf8-invalid-encoding 108 | PASS address 109 | PASS align 110 | PASS block 111 | PASS br 112 | PASS br_if 113 | PASS call 114 | PASS const 115 | PASS endianness 116 | PASS f32 117 | PASS f32_bitwise 118 | PASS f32_cmp 119 | PASS f64 120 | PASS f64_bitwise 121 | PASS f64_cmp 122 | PASS fac 123 | PASS float_misc 124 | PASS forward 125 | PASS func 126 | PASS i32 127 | PASS i64 128 | PASS if 129 | PASS int_exprs 130 | PASS int_literals 131 | PASS labels 132 | PASS left-to-right 133 | PASS load 134 | PASS local_get 135 | PASS local_set 136 | PASS local_tee 137 | PASS loop 138 | PASS nop 139 | PASS return 140 | PASS skip-stack-guard-page 141 | PASS store 142 | PASS switch 143 | PASS traps 144 | PASS type 145 | PASS unreachable 146 | PASS unreached-valid 147 | PASS unwind 148 | -------------------------------------------------------------------------------- /src/api/api.h: -------------------------------------------------------------------------------- 1 | #if !defined(WEB49_HEADER_API_API) 2 | #define WEB49_HEADER_API_API 3 | 4 | #include "../interp/interp.h" 5 | 6 | struct web49_wasi_t; 7 | typedef struct web49_wasi_t web49_wasi_t; 8 | 9 | struct web49_wasi_t { 10 | const char **argv; 11 | const char **envp; 12 | }; 13 | 14 | web49_wasi_t *web49_wasi_new(const char **argv, const char **envp); 15 | web49_env_t *web49_api_wasi(void *state, const char *module, const char *func); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | 2 | #if !defined(WEB49_HEADER_CONFIG) 3 | #define WEB49_HEADER_CONFIG 4 | 5 | #define WEB49_COUNT_ALLOC 0 6 | #define WEB49_USE_SWITCH 0 7 | #define WEB49_OPT_CONST 1 8 | #define WEB49_PRINT_AST 0 9 | #define WEB49_PRINT_INSTR 0 10 | #define WEB49_PRINT_INSTR_DEPTH 0 11 | #define WEB49_CHECK_BOUNDS 0 12 | #define WEB49_DEBUG_DIE 1 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/dep/simde/clang.h: -------------------------------------------------------------------------------- 1 | /* Detect Clang Version 2 | * Created by Evan Nemerson 3 | * 4 | * To the extent possible under law, the author(s) have dedicated all 5 | * copyright and related and neighboring rights to this software to 6 | * the public domain worldwide. This software is distributed without 7 | * any warranty. 8 | * 9 | * For details, see . 10 | * SPDX-License-Identifier: CC0-1.0 11 | */ 12 | 13 | /* This file was originally part of SIMDe 14 | * (). You're free to do with it as 15 | * you please, but I do have a few small requests: 16 | * 17 | * * If you make improvements, please submit them back to SIMDe 18 | * (at ) so others can 19 | * benefit from them. 20 | * * Please keep a link to SIMDe intact so people know where to submit 21 | * improvements. 22 | * * If you expose it publicly, please change the SIMDE_ prefix to 23 | * something specific to your project. 24 | * 25 | * The version numbers clang exposes (in the ___clang_major__, 26 | * __clang_minor__, and __clang_patchlevel__ macros) are unreliable. 27 | * Vendors such as Apple will define these values to their version 28 | * numbers; for example, "Apple Clang 4.0" is really clang 3.1, but 29 | * __clang_major__ and __clang_minor__ are defined to 4 and 0 30 | * respectively, instead of 3 and 1. 31 | * 32 | * The solution is *usually* to use clang's feature detection macros 33 | * () 34 | * to determine if the feature you're interested in is available. This 35 | * generally works well, and it should probably be the first thing you 36 | * try. Unfortunately, it's not possible to check for everything. In 37 | * particular, compiler bugs. 38 | * 39 | * This file just uses the feature checking macros to detect features 40 | * added in specific versions of clang to identify which version of 41 | * clang the compiler is based on. 42 | * 43 | * Right now it only goes back to 3.6, but I'm happy to accept patches 44 | * to go back further. And, of course, newer versions are welcome if 45 | * they're not already present, and if you find a way to detect a point 46 | * release that would be great, too! 47 | */ 48 | 49 | #if !defined(SIMDE_DETECT_CLANG_H) 50 | #define SIMDE_DETECT_CLANG_H 1 51 | 52 | /* Attempt to detect the upstream clang version number. I usually only 53 | * worry about major version numbers (at least for 4.0+), but if you 54 | * need more resolution I'm happy to accept patches that are able to 55 | * detect minor versions as well. That said, you'll probably have a 56 | * hard time with detection since AFAIK most minor releases don't add 57 | * anything we can detect. Updated based on 58 | * https://github.com/google/highway/blob/438c705a295176b96a50336527bb3e7ea365ffac/hwy/detect_compiler_arch.h#L73 59 | * - would welcome patches/updates there as well. 60 | */ 61 | 62 | #if defined(__clang__) && !defined(SIMDE_DETECT_CLANG_VERSION) 63 | #if __has_attribute(nouwtable) // no new warnings in 16.0 64 | #define SIMDE_DETECT_CLANG_VERSION 160000 65 | #elif __has_warning("-Warray-parameter") 66 | #define SIMDE_DETECT_CLANG_VERSION 150000 67 | #elif __has_warning("-Wbitwise-instead-of-logical") 68 | #define SIMDE_DETECT_CLANG_VERSION 140000 69 | #elif __has_warning("-Wwaix-compat") 70 | #define SIMDE_DETECT_CLANG_VERSION 130000 71 | #elif __has_warning("-Wformat-insufficient-args") 72 | #define SIMDE_DETECT_CLANG_VERSION 120000 73 | #elif __has_warning("-Wimplicit-const-int-float-conversion") 74 | #define SIMDE_DETECT_CLANG_VERSION 110000 75 | #elif __has_warning("-Wmisleading-indentation") 76 | #define SIMDE_DETECT_CLANG_VERSION 100000 77 | #elif defined(__FILE_NAME__) 78 | #define SIMDE_DETECT_CLANG_VERSION 90000 79 | #elif __has_warning("-Wextra-semi-stmt") || __has_builtin(__builtin_rotateleft32) 80 | #define SIMDE_DETECT_CLANG_VERSION 80000 81 | // For reasons unknown, XCode 10.3 (Apple LLVM version 10.0.1) is apparently 82 | // based on Clang 7, but does not support the warning we test. 83 | // See https://en.wikipedia.org/wiki/Xcode#Toolchain_versions and 84 | // https://trac.macports.org/wiki/XcodeVersionInfo. 85 | #elif __has_warning("-Wc++98-compat-extra-semi") || \ 86 | (defined(__apple_build_version__) && __apple_build_version__ >= 10010000) 87 | #define SIMDE_DETECT_CLANG_VERSION 70000 88 | #elif __has_warning("-Wpragma-pack") 89 | #define SIMDE_DETECT_CLANG_VERSION 60000 90 | #elif __has_warning("-Wbitfield-enum-conversion") 91 | #define SIMDE_DETECT_CLANG_VERSION 50000 92 | #elif __has_attribute(diagnose_if) 93 | #define SIMDE_DETECT_CLANG_VERSION 40000 94 | #elif __has_warning("-Wcomma") 95 | #define SIMDE_DETECT_CLANG_VERSION 39000 96 | #elif __has_warning("-Wdouble-promotion") 97 | #define SIMDE_DETECT_CLANG_VERSION 38000 98 | #elif __has_warning("-Wshift-negative-value") 99 | #define SIMDE_DETECT_CLANG_VERSION 37000 100 | #elif __has_warning("-Wambiguous-ellipsis") 101 | #define SIMDE_DETECT_CLANG_VERSION 36000 102 | #else 103 | #define SIMDE_DETECT_CLANG_VERSION 1 104 | #endif 105 | #endif /* defined(__clang__) && !defined(SIMDE_DETECT_CLANG_VERSION) */ 106 | 107 | /* The SIMDE_DETECT_CLANG_VERSION_CHECK macro is pretty 108 | * straightforward; it returns true if the compiler is a derivative 109 | * of clang >= the specified version. 110 | * 111 | * Since this file is often (primarily?) useful for working around bugs 112 | * it is also helpful to have a macro which returns true if only if the 113 | * compiler is a version of clang *older* than the specified version to 114 | * make it a bit easier to ifdef regions to add code for older versions, 115 | * such as pragmas to disable a specific warning. */ 116 | 117 | #if defined(SIMDE_DETECT_CLANG_VERSION) 118 | #define SIMDE_DETECT_CLANG_VERSION_CHECK(major, minor, revision) (SIMDE_DETECT_CLANG_VERSION >= ((major * 10000) + (minor * 1000) + (revision))) 119 | #define SIMDE_DETECT_CLANG_VERSION_NOT(major, minor, revision) (SIMDE_DETECT_CLANG_VERSION < ((major * 10000) + (minor * 1000) + (revision))) 120 | #else 121 | #define SIMDE_DETECT_CLANG_VERSION_CHECK(major, minor, revision) (0) 122 | #define SIMDE_DETECT_CLANG_VERSION_NOT(major, minor, revision) (0) 123 | #endif 124 | 125 | #endif /* !defined(SIMDE_DETECT_CLANG_H) */ 126 | -------------------------------------------------------------------------------- /src/dep/simde/trap.h: -------------------------------------------------------------------------------- 1 | /* Debugging assertions and traps 2 | * Portable Snippets - https://github.com/nemequ/portable-snippets 3 | * Created by Evan Nemerson 4 | * 5 | * To the extent possible under law, the authors have waived all 6 | * copyright and related or neighboring rights to this code. For 7 | * details, see the Creative Commons Zero 1.0 Universal license at 8 | * https://creativecommons.org/publicdomain/zero/1.0/ 9 | * 10 | * SPDX-License-Identifier: CC0-1.0 11 | */ 12 | 13 | #if !defined(SIMDE_DEBUG_TRAP_H) 14 | #define SIMDE_DEBUG_TRAP_H 15 | 16 | #if !defined(SIMDE_NDEBUG) && defined(NDEBUG) && !defined(SIMDE_DEBUG) 17 | #define SIMDE_NDEBUG 1 18 | #endif 19 | 20 | #if defined(__has_builtin) && !defined(__ibmxl__) 21 | #if __has_builtin(__builtin_debugtrap) 22 | #define simde_trap() __builtin_debugtrap() 23 | #elif __has_builtin(__debugbreak) 24 | #define simde_trap() __debugbreak() 25 | #endif 26 | #endif 27 | #if !defined(simde_trap) 28 | #if defined(_MSC_VER) || defined(__INTEL_COMPILER) 29 | #define simde_trap() __debugbreak() 30 | #elif defined(__ARMCC_VERSION) 31 | #define simde_trap() __breakpoint(42) 32 | #elif defined(__ibmxl__) || defined(__xlC__) 33 | #include 34 | #define simde_trap() __trap(42) 35 | #elif defined(__DMC__) && defined(_M_IX86) 36 | static inline void simde_trap(void) { __asm int 3h; } 37 | #elif defined(__i386__) || defined(__x86_64__) 38 | static inline void simde_trap(void) { __asm__ __volatile__("int $03"); } 39 | #elif defined(__thumb__) 40 | static inline void simde_trap(void) { __asm__ __volatile__(".inst 0xde01"); } 41 | #elif defined(__aarch64__) 42 | static inline void simde_trap(void) { __asm__ __volatile__(".inst 0xd4200000"); } 43 | #elif defined(__arm__) 44 | static inline void simde_trap(void) { __asm__ __volatile__(".inst 0xe7f001f0"); } 45 | #elif defined(__alpha__) && !defined(__osf__) 46 | static inline void simde_trap(void) { __asm__ __volatile__("bpt"); } 47 | #elif defined(_54_) 48 | static inline void simde_trap(void) { __asm__ __volatile__("ESTOP"); } 49 | #elif defined(_55_) 50 | static inline void simde_trap(void) { __asm__ __volatile__(";\n .if (.MNEMONIC)\n ESTOP_1\n .else\n ESTOP_1()\n .endif\n NOP"); } 51 | #elif defined(_64P_) 52 | static inline void simde_trap(void) { __asm__ __volatile__("SWBP 0"); } 53 | #elif defined(_6x_) 54 | static inline void simde_trap(void) { __asm__ __volatile__("NOP\n .word 0x10000000"); } 55 | #elif defined(__STDC_HOSTED__) && (__STDC_HOSTED__ == 0) && defined(__GNUC__) 56 | #define simde_trap() __builtin_trap() 57 | #else 58 | #include 59 | #if defined(SIGTRAP) 60 | #define simde_trap() raise(SIGTRAP) 61 | #else 62 | #define simde_trap() raise(SIGABRT) 63 | #endif 64 | #endif 65 | #endif 66 | 67 | #if defined(HEDLEY_LIKELY) 68 | #define SIMDE_DBG_LIKELY(expr) HEDLEY_LIKELY(expr) 69 | #elif defined(__GNUC__) && (__GNUC__ >= 3) 70 | #define SIMDE_DBG_LIKELY(expr) __builtin_expect(!!(expr), 1) 71 | #else 72 | #define SIMDE_DBG_LIKELY(expr) (!!(expr)) 73 | #endif 74 | 75 | #if !defined(SIMDE_NDEBUG) || (SIMDE_NDEBUG == 0) 76 | #define simde_dbg_assert(expr) \ 77 | do { \ 78 | if (!SIMDE_DBG_LIKELY(expr)) { \ 79 | simde_trap(); \ 80 | } \ 81 | } while (0) 82 | #else 83 | #define simde_dbg_assert(expr) 84 | #endif 85 | 86 | #endif /* !defined(SIMDE_DEBUG_TRAP_H) */ -------------------------------------------------------------------------------- /src/interp/interp.h: -------------------------------------------------------------------------------- 1 | #if !defined(WEB49_HEADER_INTERP_INTERP) 2 | #define WEB49_HEADER_INTERP_INTERP 3 | 4 | #include "../ast.h" 5 | #include "../dep/simde/simd128.h" 6 | 7 | typedef uint64_t web49_interp_instr_t; 8 | 9 | enum web49_interp_instr_enum_t { 10 | WEB49_MIN_OPCODE_INTERP = WEB49_MAX_OPCODE_NUM, 11 | WEB49_OPCODE_EXIT, 12 | WEB49_OPCODE_FFI_CALL0, 13 | WEB49_OPCODE_FFI_CALL1, 14 | WEB49_OPCODE_IF_I32_EQ, 15 | WEB49_OPCODE_IF_I32_LT_S, 16 | WEB49_OPCODE_IF_I32_LT_U, 17 | WEB49_OPCODE_IF_I32_GT_S, 18 | WEB49_OPCODE_IF_I32_GT_U, 19 | WEB49_OPCODE_IF_I64_EQ, 20 | WEB49_OPCODE_IF_I64_LT_S, 21 | WEB49_OPCODE_IF_I64_LT_U, 22 | WEB49_OPCODE_IF_I64_GT_S, 23 | WEB49_OPCODE_IF_I64_GT_U, 24 | WEB49_OPCODE_CALL_DONE0, 25 | WEB49_OPCODE_CALL_DONE1, 26 | WEB49_OPCODE_CALL_DONE2, 27 | WEB49_OPCODE_CALL_DONE4, 28 | WEB49_OPCODE_CALL_DONE8, 29 | WEB49_OPCODE_CALL_DONE16, 30 | WEB49_OPCODE_CALL_DONE32, 31 | WEB49_OPCODE_CALL_DONE64, 32 | WEB49_OPCODE_CALL_DONE128, 33 | WEB49_OPCODE_CALL_DONE256, 34 | WEB49_OPCODE_CALL_DONE512, 35 | WEB49_OPCODE_CALL_DONE1024, 36 | WEB49_MAX_OPCODE_INTERP, 37 | #if WEB49_OPT_CONST 38 | WEB49_OPCODE_WITH_CONST0 = WEB49_MAX_OPCODE_INTERP * 1, 39 | WEB49_OPCODE_WITH_CONST1 = WEB49_MAX_OPCODE_INTERP * 2, 40 | WEB49_MAX_OPCODE_INTERP_NUM = WEB49_MAX_OPCODE_INTERP * 4, 41 | #else 42 | WEB49_OPCODE_WITH_CONST1 = WEB49_MAX_OPCODE_INTERP * 1, 43 | WEB49_MAX_OPCODE_INTERP_NUM = WEB49_MAX_OPCODE_INTERP * 2, 44 | #endif 45 | }; 46 | 47 | union web49_interp_data_t; 48 | typedef union web49_interp_data_t web49_interp_data_t; 49 | 50 | struct web49_interp_t; 51 | typedef struct web49_interp_t web49_interp_t; 52 | 53 | union web49_interp_opcode_t; 54 | typedef union web49_interp_opcode_t web49_interp_opcode_t; 55 | 56 | struct web49_interp_block_t; 57 | typedef struct web49_interp_block_t web49_interp_block_t; 58 | 59 | struct web49_interp_instr_buf_t; 60 | typedef struct web49_interp_instr_buf_t web49_interp_instr_buf_t; 61 | 62 | struct web49_read_block_state_t; 63 | typedef struct web49_read_block_state_t web49_read_block_state_t; 64 | 65 | struct web49_interp_build_t; 66 | typedef struct web49_interp_build_t web49_interp_build_t; 67 | 68 | struct web49_interp_link_t; 69 | typedef struct web49_interp_link_t web49_interp_link_t; 70 | 71 | struct web49_env_t; 72 | typedef struct web49_env_t web49_env_t; 73 | 74 | struct web49_interp_table_t; 75 | typedef struct web49_interp_table_t web49_interp_table_t; 76 | 77 | typedef web49_interp_data_t (*web49_env_func_t)(void *state, web49_interp_t interp); 78 | typedef web49_env_t *(*web49_env_table_t)(void *state, const char *mod, const char *sym); 79 | 80 | struct web49_env_t { 81 | void *state; 82 | web49_env_func_t func; 83 | }; 84 | 85 | struct web49_interp_link_t { 86 | uint32_t *box; 87 | uint32_t out; 88 | }; 89 | 90 | struct web49_interp_build_t { 91 | web49_interp_opcode_t *code; 92 | uint32_t alloc; 93 | uint32_t ncode; 94 | }; 95 | 96 | union web49_interp_data_t { 97 | int64_t i64_s; 98 | int32_t i32_s; 99 | 100 | uint64_t i64_u; 101 | uint32_t i32_u; 102 | 103 | float f32; 104 | double f64; 105 | 106 | simde_v128_t *v128; 107 | }; 108 | 109 | struct web49_interp_table_t { 110 | void **restrict elems; 111 | size_t size; 112 | }; 113 | 114 | struct web49_interp_t { 115 | web49_interp_data_t *restrict locals; 116 | uint8_t *restrict memory; 117 | web49_interp_data_t *restrict globals; 118 | web49_interp_table_t *restrict tables; 119 | size_t num_tables; 120 | web49_interp_block_t *funcs; 121 | void *import_state; 122 | size_t num_env; 123 | void **env_states; 124 | web49_env_table_t *env_funcs; 125 | size_t env_alloc; 126 | void *locals_base; 127 | web49_interp_data_t **restrict stacks; 128 | web49_interp_opcode_t **restrict returns; 129 | web49_interp_data_t *yield_base; 130 | uint32_t memsize; 131 | uint32_t num_funcs; 132 | }; 133 | 134 | union web49_interp_opcode_t { 135 | #if WEB49_USE_SWTICH 136 | size_t opcode; 137 | #else 138 | void *opcode; 139 | #endif 140 | web49_interp_opcode_t *opcodes; 141 | web49_env_t *func; 142 | web49_interp_data_t data; 143 | web49_interp_block_t *block; 144 | size_t link; 145 | }; 146 | 147 | struct web49_interp_block_t { 148 | web49_interp_opcode_t *code; 149 | uint32_t nlocals : 32; 150 | uint32_t nparams : 16; 151 | uint32_t nreturns : 15; 152 | bool is_code : 1; 153 | union { 154 | struct { 155 | web49_instr_t *instrs; 156 | uint32_t num_instrs; 157 | }; 158 | struct { 159 | const char *module_str; 160 | const char *field_str; 161 | }; 162 | }; 163 | }; 164 | 165 | struct web49_read_block_state_t { 166 | void *ptrs; 167 | web49_interp_t *interp; 168 | web49_interp_build_t build; 169 | web49_interp_link_t *links; 170 | uint32_t **bufs_base; 171 | uint32_t bufs_alloc; 172 | uint32_t bufs_head; 173 | uint32_t depth; 174 | uint32_t nlocals; 175 | uint32_t alloc_links; 176 | uint32_t nlinks; 177 | }; 178 | 179 | web49_env_t *web49_env_new(void *state, web49_env_func_t func); 180 | uint32_t *web49_interp_link_box(void); 181 | void web49_interp_link_get(web49_read_block_state_t *state, uint32_t out, uint32_t *from); 182 | web49_interp_t web49_interp_module(web49_module_t mod); 183 | void web49_interp_add_import_func(web49_interp_t *ptr_interp, void *env_state, web49_env_table_t env_func); 184 | web49_interp_data_t *web49_interp_block_run(web49_interp_t *ptr_interp, web49_interp_block_t *block); 185 | uint32_t web49_interp_read_instr(web49_read_block_state_t *state, web49_instr_t cur, uint32_t local); 186 | 187 | void web49_free_interp(web49_interp_t interp); 188 | 189 | #if WEB49_CHECK_BOUNDS 190 | #define WEB49_INTERP_BOUNDS(low, add) ({ web49_error(stderr, "memmory access 0x%zx of size 0x%zx out of bounds\n", (size_t) (low), (size_t) (add)); }) 191 | #else 192 | #define WEB49_INTERP_BOUNDS(low, add) (__builtin_unreachable()) 193 | #endif 194 | #define WEB49_INTERP_ADDR(ptrtype, interp, dest, size) \ 195 | ({ \ 196 | uint32_t xptr_ = (uint32_t)(dest); \ 197 | uint32_t xsize_ = (uint32_t)(size); \ 198 | web49_interp_t sub_ = (interp); \ 199 | if (sub_.memsize < xptr_ + xsize_) { \ 200 | WEB49_INTERP_BOUNDS(xptr_, xsize_); \ 201 | }; \ 202 | (ptrtype) & sub_.memory[xptr_]; \ 203 | }) 204 | #define WEB49_INTERP_READ(elemtype, interp, src) (*WEB49_INTERP_ADDR(elemtype *, interp, src, sizeof(elemtype))) 205 | #define WEB49_INTERP_WRITE(elemtype, interp, dest, src) (*WEB49_INTERP_ADDR(elemtype *, interp, dest, sizeof(elemtype)) = (src)) 206 | #define WEB49_INTERP_V128(n) \ 207 | ({ \ 208 | simde_v128_t *ptr = web49_malloc(sizeof(simde_v128_t));\ 209 | *(__uint128_t *)ptr = *(__uint128_t *)&(n); \ 210 | ptr; \ 211 | }) 212 | 213 | #endif 214 | -------------------------------------------------------------------------------- /src/interp/interp0.inc: -------------------------------------------------------------------------------- 1 | NAME(WEB49_OPCODE_MEMORY_INIT) { 2 | web49_error("memory init?\n"); 3 | NEXT(); 4 | } 5 | NAME(WEB49_OPCODE_DATA_DROP) { 6 | web49_error("data drop? \n"); 7 | NEXT(); 8 | } 9 | NAME(WEB49_OPCODE_TABLE_INIT) { 10 | web49_error("table init? \n"); 11 | NEXT(); 12 | } 13 | NAME(WEB49_OPCODE_ELEM_DROP) { 14 | web49_error("elem drop?\n"); 15 | NEXT(); 16 | } 17 | NAME(WEB49_OPCODE_TABLE_COPY) { 18 | web49_error("table copy?\n"); 19 | NEXT(); 20 | } 21 | NAME(WEB49_OPCODE_FFI_CALL1) { 22 | #if WEB49_PRINT_INSTR_DEPTH 23 | depth -= 1; 24 | #endif 25 | interp.locals = locals; 26 | web49_env_t *func = head[0].func; 27 | locals[0] = func->func(func->state, interp); 28 | head = *--returns; 29 | locals = *--stacks; 30 | NEXT(); 31 | } 32 | NAME(WEB49_OPCODE_FFI_CALL0) { 33 | #if WEB49_PRINT_INSTR_DEPTH 34 | depth -= 1; 35 | #endif 36 | interp.locals = locals; 37 | web49_env_t *func = head[0].func; 38 | func->func(func->state, interp); 39 | head = *--returns; 40 | locals = *--stacks; 41 | NEXT(); 42 | } 43 | NAME(WEB49_OPCODE_YIELD_POP) { 44 | locals[head[0].data.i32_u] = *--yield_ptr; 45 | head += 1; 46 | NEXT(); 47 | } 48 | NAME(WEB49_OPCODE_RETURN0) { 49 | #if WEB49_PRINT_INSTR_DEPTH 50 | depth -= 1; 51 | #endif 52 | head = *--returns; 53 | locals = *--stacks; 54 | NEXT(); 55 | } 56 | NAME(WEB49_OPCODE_CALL_DONE0) { 57 | #if WEB49_PRINT_INSTR_DEPTH 58 | depth += 1; 59 | #endif 60 | *returns++ = head + 3; 61 | *stacks++ = locals; 62 | locals += head[2].data.i32_u; 63 | head = head[0].opcodes; 64 | NEXT(); 65 | } 66 | NAME(WEB49_OPCODE_CALL_DONE1) { 67 | #if WEB49_PRINT_INSTR_DEPTH 68 | depth += 1; 69 | #endif 70 | *returns++ = head + 3; 71 | *stacks++ = locals; 72 | locals += head[2].data.i32_u; 73 | locals[head[1].data.i32_u + 0].i64_u = 0; 74 | head = head[0].opcodes; 75 | NEXT(); 76 | } 77 | NAME(WEB49_OPCODE_CALL_DONE2) { 78 | #if WEB49_PRINT_INSTR_DEPTH 79 | depth += 1; 80 | #endif 81 | *returns++ = head + 3; 82 | *stacks++ = locals; 83 | locals += head[2].data.i32_u; 84 | locals[head[1].data.i32_u + 0].i64_u = 0; 85 | locals[head[1].data.i32_u + 1].i64_u = 0; 86 | head = head[0].opcodes; 87 | NEXT(); 88 | } 89 | NAME(WEB49_OPCODE_CALL_DONE4) { 90 | #if WEB49_PRINT_INSTR_DEPTH 91 | depth += 1; 92 | #endif 93 | *returns++ = head + 3; 94 | *stacks++ = locals; 95 | locals += head[2].data.i32_u; 96 | memset(locals + head[1].data.i32_u, 0, sizeof(web49_interp_data_t) * 4); 97 | head = head[0].opcodes; 98 | NEXT(); 99 | } 100 | NAME(WEB49_OPCODE_CALL_DONE8) { 101 | #if WEB49_PRINT_INSTR_DEPTH 102 | depth += 1; 103 | #endif 104 | *returns++ = head + 3; 105 | *stacks++ = locals; 106 | locals += head[2].data.i32_u; 107 | memset(locals + head[1].data.i32_u, 0, sizeof(web49_interp_data_t) * 8); 108 | head = head[0].opcodes; 109 | NEXT(); 110 | } 111 | NAME(WEB49_OPCODE_CALL_DONE16) { 112 | #if WEB49_PRINT_INSTR_DEPTH 113 | depth += 1; 114 | #endif 115 | *returns++ = head + 3; 116 | *stacks++ = locals; 117 | locals += head[2].data.i32_u; 118 | memset(locals + head[1].data.i32_u, 0, sizeof(web49_interp_data_t) * 16); 119 | head = head[0].opcodes; 120 | NEXT(); 121 | } 122 | NAME(WEB49_OPCODE_CALL_DONE32) { 123 | #if WEB49_PRINT_INSTR_DEPTH 124 | depth += 1; 125 | #endif 126 | *returns++ = head + 3; 127 | *stacks++ = locals; 128 | locals += head[2].data.i32_u; 129 | memset(locals + head[1].data.i32_u, 0, sizeof(web49_interp_data_t) * 32); 130 | head = head[0].opcodes; 131 | NEXT(); 132 | } 133 | NAME(WEB49_OPCODE_CALL_DONE64) { 134 | #if WEB49_PRINT_INSTR_DEPTH 135 | depth += 1; 136 | #endif 137 | *returns++ = head + 3; 138 | *stacks++ = locals; 139 | locals += head[2].data.i32_u; 140 | memset(locals + head[1].data.i32_u, 0, sizeof(web49_interp_data_t) * 64); 141 | head = head[0].opcodes; 142 | NEXT(); 143 | } 144 | NAME(WEB49_OPCODE_CALL_DONE128) { 145 | #if WEB49_PRINT_INSTR_DEPTH 146 | depth += 1; 147 | #endif 148 | *returns++ = head + 3; 149 | *stacks++ = locals; 150 | locals += head[2].data.i32_u; 151 | memset(locals + head[1].data.i32_u, 0, sizeof(web49_interp_data_t) * 128); 152 | head = head[0].opcodes; 153 | NEXT(); 154 | } 155 | NAME(WEB49_OPCODE_CALL_DONE256) { 156 | #if WEB49_PRINT_INSTR_DEPTH 157 | depth += 1; 158 | #endif 159 | *returns++ = head + 3; 160 | *stacks++ = locals; 161 | locals += head[2].data.i32_u; 162 | memset(locals + head[1].data.i32_u, 0, sizeof(web49_interp_data_t) * 256); 163 | head = head[0].opcodes; 164 | NEXT(); 165 | } 166 | NAME(WEB49_OPCODE_CALL_DONE512) { 167 | #if WEB49_PRINT_INSTR_DEPTH 168 | depth += 1; 169 | #endif 170 | *returns++ = head + 3; 171 | *stacks++ = locals; 172 | locals += head[2].data.i32_u; 173 | memset(locals + head[1].data.i32_u, 0, sizeof(web49_interp_data_t) * 512); 174 | head = head[0].opcodes; 175 | NEXT(); 176 | } 177 | NAME(WEB49_OPCODE_CALL_DONE1024) { 178 | #if WEB49_PRINT_INSTR_DEPTH 179 | depth += 1; 180 | #endif 181 | *returns++ = head + 3; 182 | *stacks++ = locals; 183 | locals += head[2].data.i32_u; 184 | memset(locals + head[1].data.i32_u, 0, sizeof(web49_interp_data_t) * 1024); 185 | head = head[0].opcodes; 186 | NEXT(); 187 | } 188 | NAME(WEB49_OPCODE_CALL) { 189 | #if WEB49_PRINT_INSTR_DEPTH 190 | depth += 1; 191 | #endif 192 | web49_interp_block_t *fblock = head[0].block; 193 | web49_interp_block_run_comp(fblock, ptrs, interp); 194 | *returns++ = head + 3; 195 | *stacks++ = locals; 196 | locals += head[2].data.i32_u; 197 | memset(locals + fblock->nparams, 0, sizeof(web49_interp_data_t) * fblock->nlocals); 198 | if (fblock->nlocals == 0) { 199 | head[-1].opcode = OPCODE(WEB49_OPCODE_CALL_DONE0); 200 | } else if (fblock->nlocals <= 1) { 201 | head[-1].opcode = OPCODE(WEB49_OPCODE_CALL_DONE1); 202 | } else if (fblock->nlocals <= 2) { 203 | head[-1].opcode = OPCODE(WEB49_OPCODE_CALL_DONE2); 204 | } else if (fblock->nlocals <= 4) { 205 | head[-1].opcode = OPCODE(WEB49_OPCODE_CALL_DONE4); 206 | } else if (fblock->nlocals <= 8) { 207 | head[-1].opcode = OPCODE(WEB49_OPCODE_CALL_DONE8); 208 | } else if (fblock->nlocals <= 16) { 209 | head[-1].opcode = OPCODE(WEB49_OPCODE_CALL_DONE16); 210 | } else if (fblock->nlocals <= 32) { 211 | head[-1].opcode = OPCODE(WEB49_OPCODE_CALL_DONE32); 212 | } else if (fblock->nlocals <= 64) { 213 | head[-1].opcode = OPCODE(WEB49_OPCODE_CALL_DONE64); 214 | } else if (fblock->nlocals <= 128) { 215 | head[-1].opcode = OPCODE(WEB49_OPCODE_CALL_DONE128); 216 | } else if (fblock->nlocals <= 256) { 217 | head[-1].opcode = OPCODE(WEB49_OPCODE_CALL_DONE256); 218 | } else if (fblock->nlocals <= 512) { 219 | head[-1].opcode = OPCODE(WEB49_OPCODE_CALL_DONE512); 220 | } else if (fblock->nlocals <= 1024) { 221 | head[-1].opcode = OPCODE(WEB49_OPCODE_CALL_DONE1024); 222 | } else { 223 | web49_error("too many locals: %zu\n", (size_t)fblock->nlocals); 224 | __builtin_trap(); 225 | } 226 | head[0].opcodes = fblock->code; 227 | head[1].data.i32_u = fblock->nparams; 228 | head = fblock->code; 229 | NEXT(); 230 | } 231 | NAME(WEB49_OPCODE_BR) { 232 | head = head[0].opcodes; 233 | NEXT(); 234 | } 235 | NAME(WEB49_OPCODE_GET_LOCAL) { 236 | locals[head[0].data.i32_u] = locals[head[1].data.i32_u]; 237 | head += 2; 238 | NEXT(); 239 | } 240 | NAME(WEB49_OPCODE_GET_GLOBAL) { 241 | locals[head[0].data.i32_u] = interp.globals[head[1].data.i32_u]; 242 | head += 2; 243 | NEXT(); 244 | } 245 | NAME(WEB49_OPCODE_MEMORY_SIZE) { 246 | locals[head[0].data.i32_u].i32_u = interp.memsize / 65536; 247 | head += 1; 248 | NEXT(); 249 | } 250 | NAME(WEB49_OPCODE_I32_CONST) { 251 | locals[head[0].data.i32_u] = head[1].data; 252 | head += 2; 253 | NEXT(); 254 | } 255 | NAME(WEB49_OPCODE_I64_CONST) { 256 | locals[head[0].data.i32_u] = head[1].data; 257 | head += 2; 258 | NEXT(); 259 | } 260 | NAME(WEB49_OPCODE_F32_CONST) { 261 | locals[head[0].data.i32_u] = head[1].data; 262 | head += 2; 263 | NEXT(); 264 | } 265 | NAME(WEB49_OPCODE_F64_CONST) { 266 | locals[head[0].data.i32_u] = head[1].data; 267 | head += 2; 268 | NEXT(); 269 | } 270 | -------------------------------------------------------------------------------- /src/io.c: -------------------------------------------------------------------------------- 1 | 2 | #include "./io.h" 3 | 4 | web49_io_input_t web49_io_input_open_str(size_t len, uint8_t *str) { 5 | uint8_t *buf = web49_malloc(sizeof(uint8_t) * len); 6 | memcpy(buf, str, len); 7 | return (web49_io_input_t){ 8 | .byte_index = 0, 9 | .byte_len = len, 10 | .byte_buf = buf, 11 | }; 12 | } 13 | 14 | web49_io_input_t web49_io_input_open(const char *filename) { 15 | if (filename == NULL) { 16 | web49_error("no input file given\n"); 17 | } 18 | FILE *file = fopen(filename, "rb"); 19 | if (file == NULL) { 20 | web49_error("cannot open file: %s\n", filename); 21 | } 22 | size_t len = 0; 23 | uint8_t *str = NULL; 24 | size_t alloc = 512; 25 | str = web49_malloc(sizeof(uint8_t) * alloc); 26 | while (!feof(file)) { 27 | if (len + 256 >= alloc) { 28 | alloc = (len + 256) * 2; 29 | str = web49_realloc(str, sizeof(uint8_t) * alloc); 30 | } 31 | len += fread(&str[len], 1, 128, file); 32 | } 33 | str[len] = 0; 34 | fclose(file); 35 | return (web49_io_input_t){ 36 | .byte_index = 0, 37 | .byte_len = len, 38 | .byte_buf = str, 39 | }; 40 | } 41 | bool web49_io_input_is_empty(web49_io_input_t *in) { 42 | return in->byte_len == in->byte_index; 43 | } 44 | size_t web49_io_input_ftell(web49_io_input_t *in) { 45 | return in->byte_index; 46 | } 47 | size_t web49_io_input_fread(web49_io_input_t *in, size_t size, void *data) { 48 | memcpy(data, &in->byte_buf[in->byte_index], size); 49 | in->byte_index += size; 50 | return size; 51 | } 52 | char web49_io_input_fgetc(web49_io_input_t *in) { 53 | return (char)in->byte_buf[in->byte_index++]; 54 | } 55 | void web49_io_input_rewind(web49_io_input_t *in) { 56 | in->byte_index -= 1; 57 | } 58 | void web49_file_output_dump(web49_io_output_t out, const char *filename) { 59 | if (filename == NULL) { 60 | web49_error("no output file given\n"); 61 | } 62 | FILE *file = fopen(filename, "wb"); 63 | if (file == NULL) { 64 | web49_error("cannot open file: %s\n", filename); 65 | } 66 | fwrite(out.byte_buf, 1, out.byte_index, file); 67 | fclose(file); 68 | } 69 | void web49_io_output_fprintf(web49_io_output_t *out, const char *format, ...) { 70 | if (out->byte_index + 2048 >= out->byte_alloc) { 71 | out->byte_alloc = (out->byte_index + 2048) * 2; 72 | out->byte_buf = web49_realloc(out->byte_buf, sizeof(uint8_t) * out->byte_alloc); 73 | } 74 | va_list ap; 75 | va_start(ap, format); 76 | out->byte_index += (size_t)vsnprintf((char *)&out->byte_buf[out->byte_index], out->byte_alloc - out->byte_index, format, ap); 77 | va_end(ap); 78 | } 79 | void web49_io_output_write_len_str(web49_io_output_t *out, size_t len, const char *str) { 80 | if (out->byte_index + len + (2048) >= out->byte_alloc) { 81 | out->byte_alloc = (out->byte_index + len + 2048) * 2; 82 | out->byte_buf = web49_realloc(out->byte_buf, sizeof(uint8_t) * out->byte_alloc); 83 | } 84 | memcpy(&out->byte_buf[out->byte_index], str, len); 85 | out->byte_index += len; 86 | } 87 | -------------------------------------------------------------------------------- /src/io.h: -------------------------------------------------------------------------------- 1 | #if !defined(WEB49_HEADER_IO) 2 | #define WEB49_HEADER_IO 3 | 4 | #include "./lib.h" 5 | 6 | struct web49_io_input_t; 7 | typedef struct web49_io_input_t web49_io_input_t; 8 | 9 | struct web49_io_output_t; 10 | typedef struct web49_io_output_t web49_io_output_t; 11 | 12 | struct web49_io_input_t { 13 | size_t byte_index; 14 | size_t byte_len; 15 | uint8_t *byte_buf; 16 | }; 17 | 18 | struct web49_io_output_t { 19 | size_t byte_index; 20 | size_t byte_alloc; 21 | uint8_t *byte_buf; 22 | }; 23 | 24 | web49_io_input_t web49_io_input_open_str(size_t len, uint8_t *str); 25 | web49_io_input_t web49_io_input_open(const char *filename); 26 | bool web49_io_input_is_empty(web49_io_input_t *input); 27 | size_t web49_io_input_ftell(web49_io_input_t *in); 28 | size_t web49_io_input_fread(web49_io_input_t *in, size_t size, void *data); 29 | char web49_io_input_fgetc(web49_io_input_t *in); 30 | void web49_io_input_rewind(web49_io_input_t *in); 31 | 32 | void web49_file_output_dump(web49_io_output_t out, const char *filename); 33 | void web49_io_output_fprintf(web49_io_output_t *out, const char *format, ...); 34 | void web49_io_output_write_len_str(web49_io_output_t *out, size_t len, const char *str); 35 | 36 | #define web49_io_output_write_str(out, str) web49_io_output_write_len_str(out, strlen(str), str) 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/lib.c: -------------------------------------------------------------------------------- 1 | #include "./lib.h" 2 | 3 | #if WEB49_COUNT_ALLOC 4 | size_t web49_total_alloc = 0; 5 | #endif 6 | 7 | char *web49_format_float(float num) { 8 | size_t size = snprintf(NULL, 0, "%f", num); 9 | char *str = malloc(sizeof(char) * (size + 1)); 10 | snprintf(str, size + 1, "%f", num); 11 | return str; 12 | } 13 | char *web49_format_double(double num) { 14 | size_t size = snprintf(NULL, 0, "%lf", num); 15 | char *str = malloc(sizeof(char) * (size + 1)); 16 | snprintf(str, size + 1, "%lf", num); 17 | return str; 18 | } -------------------------------------------------------------------------------- /src/lib.h: -------------------------------------------------------------------------------- 1 | 2 | #if !defined(WEB49_HEADER_LIB) 3 | #define WEB49_HEADER_LIB 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "./config.h" 20 | 21 | #define web49_parse_float_to(str, ptr) (sscanf((str), "%f", (ptr))) 22 | #define web49_parse_double_to(str, ptr) (sscanf((str), "%lf", (ptr))) 23 | 24 | #if defined(_WIN32) 25 | #define getentropy(buf, len) ((int)0) 26 | #else 27 | int getentropy(void *buffer, size_t length); 28 | #endif 29 | 30 | #if WEB49_COUNT_ALLOC 31 | extern size_t web49_total_alloc; 32 | #define web49_req_mem(size) (web49_total_alloc += (size)) 33 | #else 34 | #define web49_req_mem(size) ((void)(size)) 35 | #endif 36 | 37 | #define web49_malloc(size) (malloc(size)) 38 | #define web49_alloc0(size) (calloc(size, 1)) 39 | #define web49_realloc(ptr, size) (realloc(ptr, size)) 40 | #define web49_free(ptr) (free((void *)ptr)) 41 | 42 | #define web49_unreachable() __builtin_unreachable() 43 | 44 | #if WEB49_DEBUG_DIE 45 | #define web49_die() __builtin_trap() 46 | #else 47 | #define web49_die() exit(1) 48 | #endif 49 | 50 | #define web49_error(...) \ 51 | fprintf(stderr, __VA_ARGS__); \ 52 | web49_die() 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/opt/tee.c: -------------------------------------------------------------------------------- 1 | #include "./tee.h" 2 | 3 | #include "../tables.h" 4 | 5 | void web49_opt_tee_instr(web49_instr_t *instr) { 6 | uint32_t len = instr->nargs; 7 | for (size_t i = 0; i < instr->nargs; i++) { 8 | if (instr->args[i].opcode == WEB49_OPCODE_TEE_LOCAL) { 9 | len += 1; 10 | } 11 | } 12 | if (len != instr->nargs) { 13 | web49_instr_t *next = web49_malloc(sizeof(web49_instr_t) * len); 14 | size_t len = 0; 15 | for (size_t i = 0; i < instr->nargs; i++) { 16 | web49_instr_t sub = instr->args[i]; 17 | if (sub.opcode == WEB49_OPCODE_TEE_LOCAL) { 18 | next[len++] = (web49_instr_t){ 19 | .opcode = WEB49_OPCODE_SET_LOCAL, 20 | .immediate = sub.immediate, 21 | }; 22 | next[len++] = (web49_instr_t){ 23 | .opcode = WEB49_OPCODE_GET_LOCAL, 24 | .immediate = sub.immediate, 25 | }; 26 | } else if (sub.opcode == WEB49_OPCODE_NOP) { 27 | } else { 28 | next[len++] = sub; 29 | } 30 | } 31 | web49_free(instr->args); 32 | instr->nargs = len; 33 | instr->args = next; 34 | } 35 | for (size_t i = 0; i < instr->nargs; i++) { 36 | web49_opt_tee_instr(&instr->args[i]); 37 | } 38 | } 39 | 40 | void web49_opt_tee_code(web49_section_code_entry_t *entry) { 41 | uint32_t len = 0; 42 | uint32_t alloc = entry->num_instrs + 16; 43 | web49_instr_t *next = web49_malloc(sizeof(web49_instr_t) * alloc); 44 | for (uint32_t i = 0; i < entry->num_instrs; i++) { 45 | web49_instr_t instr = entry->instrs[i]; 46 | // web49_opt_tee_instr(&instr); 47 | if (len + 2 >= alloc) { 48 | alloc = (len + 2) * 2; 49 | next = web49_realloc(next, sizeof(web49_instr_t) * alloc); 50 | } 51 | if (instr.opcode == WEB49_OPCODE_TEE_LOCAL) { 52 | next[len++] = (web49_instr_t){ 53 | .opcode = WEB49_OPCODE_SET_LOCAL, 54 | .immediate = instr.immediate, 55 | }; 56 | next[len++] = (web49_instr_t){ 57 | .opcode = WEB49_OPCODE_GET_LOCAL, 58 | .immediate = instr.immediate, 59 | }; 60 | web49_free_instr(instr); 61 | } else if (instr.opcode == WEB49_OPCODE_NOP) { 62 | } else { 63 | next[len++] = instr; 64 | } 65 | } 66 | web49_free(entry->instrs); 67 | entry->num_instrs = len; 68 | entry->instrs = next; 69 | for (uint32_t i = 0; i < entry->num_instrs; i++) { 70 | web49_opt_tee_instr(&entry->instrs[i]); 71 | } 72 | } 73 | 74 | void web49_opt_tee_module(web49_module_t *mod) { 75 | for (uint64_t s = 0; s < mod->num_sections; s++) { 76 | web49_section_t cur = mod->sections[s]; 77 | if (cur.header.id == WEB49_SECTION_ID_CODE) { 78 | for (uint64_t i = 0; i < cur.code_section.num_entries; i++) { 79 | web49_opt_tee_code(&cur.code_section.entries[i]); 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/opt/tee.h: -------------------------------------------------------------------------------- 1 | #if !defined(WEB49_HEADER_OPT_TEE) 2 | #define WEB49_HEADER_OPT_TEE 3 | 4 | #include "../ast.h" 5 | 6 | void web49_opt_tee_code(web49_section_code_entry_t *entry); 7 | void web49_opt_tee_module(web49_module_t *mod); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/opt/tree.h: -------------------------------------------------------------------------------- 1 | #if !defined(WEB49_HEADER_OPT_TREE) 2 | #define WEB49_HEADER_OPT_TREE 3 | 4 | #include "../ast.h" 5 | 6 | void web49_opt_tree_module(web49_module_t *mod); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/read_bin.h: -------------------------------------------------------------------------------- 1 | 2 | #if !defined(WEB49_HEADER_READBIN) 3 | #define WEB49_HEADER_READBIN 4 | 5 | #include "./ast.h" 6 | #include "./io.h" 7 | 8 | uint64_t web49_readbin_uleb(web49_io_input_t *in); 9 | int64_t web49_readbin_sleb(web49_io_input_t *in); 10 | uint8_t web49_readbin_byte(web49_io_input_t *in); 11 | web49_preamble_t web49_readbin_preamble(web49_io_input_t *in); 12 | web49_section_header_t web49_readbin_section_header(web49_io_input_t *in); 13 | uint8_t web49_readbin_varuint1(web49_io_input_t *in); 14 | int32_t web49_readbin_varuint32(web49_io_input_t *in); 15 | int64_t web49_readbin_varuint64(web49_io_input_t *in); 16 | uint32_t web49_readbin_uint32(web49_io_input_t *in); 17 | uint64_t web49_readbin_uint64(web49_io_input_t *in); 18 | web49_block_type_t web49_readbin_block_type(web49_io_input_t *in); 19 | web49_br_table_t web49_readbin_br_table(web49_io_input_t *in); 20 | web49_call_indirect_t web49_readbin_call_indirect(web49_io_input_t *in); 21 | web49_memory_immediate_t web49_readbin_memory_immediate(web49_io_input_t *in); 22 | web49_type_function_t web49_readbin_type_function(web49_io_input_t *in); 23 | web49_type_table_t web49_readbin_type_table(web49_io_input_t *in); 24 | web49_type_global_t web49_readbin_type_global(web49_io_input_t *in); 25 | web49_limits_t web49_readbin_limits(web49_io_input_t *in); 26 | web49_type_t web49_readbin_type(web49_io_input_t *in, web49_tag_t tag); 27 | web49_section_custom_t web49_readbin_section_custom(web49_io_input_t *in, web49_section_header_t header); 28 | web49_section_type_t web49_readbin_section_type(web49_io_input_t *in); 29 | web49_section_import_t web49_readbin_section_import(web49_io_input_t *in); 30 | web49_section_function_t web49_readbin_section_function(web49_io_input_t *in); 31 | web49_section_table_t web49_readbin_section_table(web49_io_input_t *in); 32 | web49_section_memory_t web49_readbin_section_memory(web49_io_input_t *in); 33 | web49_section_global_t web49_readbin_section_global(web49_io_input_t *in); 34 | web49_section_export_t web49_readbin_section_export(web49_io_input_t *in); 35 | web49_section_start_t web49_readbin_section_start(web49_io_input_t *in); 36 | web49_section_element_t web49_readbin_section_element(web49_io_input_t *in); 37 | web49_section_code_t web49_readbin_section_code(web49_io_input_t *in); 38 | web49_section_data_t web49_readbin_section_data(web49_io_input_t *in); 39 | web49_instr_immediate_t web49_readbin_instr_immediate(web49_io_input_t *in, web49_immediate_id_t id); 40 | web49_instr_t web49_readbin_init_expr(web49_io_input_t *in); 41 | web49_instr_t web49_readbin_instr(web49_io_input_t *in); 42 | web49_section_t web49_readbin_section(web49_io_input_t *in, web49_section_header_t id); 43 | web49_module_t web49_readbin_module(web49_io_input_t *in); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/read_wat.h: -------------------------------------------------------------------------------- 1 | 2 | #if !defined(WEB49_HEADER_READWAT) 3 | #define WEB49_HEADER_READWAT 4 | 5 | #include "./ast.h" 6 | #include "./io.h" 7 | enum { 8 | WEB49_READWAT_EXPR_TAG_INIT, 9 | WEB49_READWAT_EXPR_TAG_FUN, 10 | WEB49_READWAT_EXPR_TAG_SYM, 11 | WEB49_READWAT_EXPR_TAG_STR, 12 | }; 13 | 14 | struct web49_readwat_table_t; 15 | typedef struct web49_readwat_table_t web49_readwat_table_t; 16 | 17 | struct web49_readwat_state_t; 18 | typedef struct web49_readwat_state_t web49_readwat_state_t; 19 | 20 | struct web49_readwat_expr_t; 21 | typedef struct web49_readwat_expr_t web49_readwat_expr_t; 22 | 23 | void web49_readwat_skip(web49_io_input_t *in); 24 | const char *web49_readwat_sym_to_str(web49_readwat_expr_t expr); 25 | web49_instr_t web49_readwat_instr(web49_readwat_state_t *out, web49_readwat_expr_t code); 26 | uint64_t web49_readwat_expr_to_u64f(web49_readwat_expr_t expr); 27 | uint32_t web49_readwat_expr_to_u32f(web49_readwat_expr_t expr); 28 | uint64_t web49_readwat_expr_to_u64(web49_readwat_table_t *table, web49_readwat_expr_t expr); 29 | int64_t web49_readwat_expr_to_i64(web49_readwat_expr_t expr); 30 | web49_readwat_expr_t web49_readwat_expr_base(web49_io_input_t *in); 31 | web49_readwat_expr_t web49_readwat_expr(web49_io_input_t *in); 32 | void web49_readwat_state_type_entry(web49_readwat_state_t *out, web49_readwat_expr_t expr); 33 | void web49_readwat_state_import_entry(web49_readwat_state_t *out, web49_readwat_expr_t expr); 34 | void web49_readwat_state_func_entry(web49_readwat_state_t *out, web49_readwat_expr_t expr); 35 | void web49_readwat_state_table_entry(web49_readwat_state_t *out, web49_readwat_expr_t expr); 36 | void web49_readwat_state_global_entry(web49_readwat_state_t *out, web49_readwat_expr_t expr); 37 | void web49_readwat_state_export_entry(web49_readwat_state_t *out, web49_readwat_expr_t expr); 38 | void web49_readwat_state_elem_entry(web49_readwat_state_t *out, web49_readwat_expr_t expr); 39 | void web49_readwat_state_data_entry(web49_readwat_state_t *out, web49_readwat_expr_t expr); 40 | void web49_readwat_state_memory_entry(web49_readwat_state_t *out, web49_readwat_expr_t expr); 41 | 42 | struct web49_readwat_table_t { 43 | uint64_t len; 44 | const char **key; 45 | uint64_t *value; 46 | uint64_t alloc; 47 | }; 48 | 49 | struct web49_readwat_state_t { 50 | uint64_t num_func_imports; 51 | uint64_t block_depth; 52 | 53 | web49_readwat_table_t func_table; 54 | web49_readwat_table_t type_table; 55 | web49_readwat_table_t local_table; 56 | web49_readwat_table_t branch_table; 57 | web49_readwat_table_t global_table; 58 | web49_readwat_table_t table_table; 59 | web49_readwat_table_t memory_table; 60 | 61 | uint64_t alloc_type; 62 | uint64_t alloc_import; 63 | uint64_t alloc_function; 64 | uint64_t alloc_table; 65 | uint64_t alloc_global; 66 | uint64_t alloc_memory; 67 | uint64_t alloc_export; 68 | uint64_t alloc_element; 69 | uint64_t alloc_code; 70 | uint64_t alloc_data; 71 | 72 | web49_section_type_t stype; 73 | web49_section_import_t simport; 74 | web49_section_function_t sfunction; 75 | web49_section_table_t stable; 76 | web49_section_global_t sglobal; 77 | web49_section_memory_t smemory; 78 | web49_section_export_t sexport; 79 | web49_section_element_t selement; 80 | web49_section_code_t scode; 81 | web49_section_data_t sdata; 82 | }; 83 | 84 | struct web49_readwat_expr_t { 85 | uint64_t start; 86 | uint64_t end; 87 | union { 88 | struct { 89 | const char *fun_fun; 90 | uint64_t fun_nargs; 91 | web49_readwat_expr_t *fun_args; 92 | }; 93 | struct { 94 | uint64_t len_str; 95 | uint8_t *str; 96 | }; 97 | const char *sym; 98 | }; 99 | uint8_t tag; 100 | }; 101 | 102 | const char *web49_readwat_name(web49_io_input_t *in); 103 | web49_module_t web49_readwat_module(web49_io_input_t *in); 104 | web49_module_t web49_readwat_to_module(web49_readwat_expr_t expr); 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /src/tables.h: -------------------------------------------------------------------------------- 1 | 2 | #if !defined(WEB49_HEADER_TABLES) 3 | #define WEB49_HEADER_TABLES 4 | 5 | #include "./ast.h" 6 | 7 | struct web49_table_stack_effect_t; 8 | typedef struct web49_table_stack_effect_t web49_table_stack_effect_t; 9 | 10 | enum { 11 | WEB49_TABLE_STACK_EFFECT_END, 12 | WEB49_TABLE_STACK_EFFECT_ANY, 13 | WEB49_TABLE_STACK_EFFECT_ARGS, 14 | WEB49_TABLE_STACK_EFFECT_ARGS_INDIRECT, 15 | WEB49_TABLE_STACK_EFFECT_BLOCK, 16 | WEB49_TABLE_STACK_EFFECT_RET, 17 | WEB49_TABLE_STACK_EFFECT_RET_INDIRECT, 18 | WEB49_TABLE_STACK_EFFECT_I32, 19 | WEB49_TABLE_STACK_EFFECT_I64, 20 | WEB49_TABLE_STACK_EFFECT_F32, 21 | WEB49_TABLE_STACK_EFFECT_F64, 22 | WEB49_TABLE_STACK_EFFECT_V128, 23 | }; 24 | 25 | struct web49_table_stack_effect_t { 26 | uint8_t in[8]; 27 | uint8_t out[8]; 28 | bool branch : 1; 29 | bool fail : 1; 30 | }; 31 | 32 | bool web49_opcode_is_simd(web49_opcode_t); 33 | size_t web49_opcode_byte_count(uint8_t first_byte); 34 | web49_opcode_t web49_bytes_to_opcode(uint8_t *bytes); 35 | void web49_opcode_to_bytes(web49_opcode_t opcode, size_t *out_len, uint8_t *out_bytes); 36 | uint8_t web49_opcode_skip(web49_opcode_t opcode); 37 | extern const web49_table_stack_effect_t web49_stack_effects[WEB49_MAX_OPCODE_NUM]; 38 | extern const size_t web49_opcode_memsize[WEB49_MAX_OPCODE_NUM]; 39 | extern const web49_immediate_id_t web49_opcode_immediate[WEB49_MAX_OPCODE_NUM]; 40 | web49_opcode_t web49_name_to_opcode(const char *name); 41 | const char *web49_opcode_to_name(web49_opcode_t opcode); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/write_bin.h: -------------------------------------------------------------------------------- 1 | 2 | #if !defined(WEB49_HEADER_WRITEBIN) 3 | #define WEB49_HEADER_WRITEBIN 4 | 5 | #include "./ast.h" 6 | 7 | struct web49_writebin_buf_t; 8 | typedef struct web49_writebin_buf_t web49_writebin_buf_t; 9 | 10 | struct web49_writebin_buf_t { 11 | uint8_t *data; 12 | size_t len; 13 | size_t alloc; 14 | }; 15 | 16 | void web49_writebin_uleb(web49_writebin_buf_t *out, uint64_t x); 17 | void web49_writebin_sleb(web49_writebin_buf_t *out, int64_t x); 18 | 19 | void web49_writebin_type_function(web49_writebin_buf_t *out, web49_type_function_t type); 20 | void web49_writebin_type_table(web49_writebin_buf_t *out, web49_type_table_t type); 21 | void web49_writebin_type_memory(web49_writebin_buf_t *out, web49_limits_t type); 22 | void web49_writebin_type_global(web49_writebin_buf_t *out, web49_type_global_t type); 23 | void web49_writebin_type(web49_writebin_buf_t *out, web49_type_t type); 24 | 25 | void web49_writebin_instr(web49_writebin_buf_t *out, web49_instr_t instr); 26 | 27 | void web49_writebin_section_custom(web49_writebin_buf_t *out, web49_section_t mod); 28 | void web49_writebin_section_type(web49_writebin_buf_t *out, web49_section_t mod); 29 | void web49_writebin_section_import(web49_writebin_buf_t *out, web49_section_t mod); 30 | void web49_writebin_section_function(web49_writebin_buf_t *out, web49_section_t mod); 31 | void web49_writebin_section_table(web49_writebin_buf_t *out, web49_section_t mod); 32 | void web49_writebin_section_memory(web49_writebin_buf_t *out, web49_section_t mod); 33 | void web49_writebin_section_global(web49_writebin_buf_t *out, web49_section_t mod); 34 | void web49_writebin_section_export(web49_writebin_buf_t *out, web49_section_t mod); 35 | void web49_writebin_section_start(web49_writebin_buf_t *out, web49_section_t mod); 36 | void web49_writebin_section_element(web49_writebin_buf_t *out, web49_section_t mod); 37 | void web49_writebin_section_code(web49_writebin_buf_t *out, web49_section_t mod); 38 | void web49_writebin_section_data(web49_writebin_buf_t *out, web49_section_t mod); 39 | 40 | void web49_writebin_section(web49_writebin_buf_t *out, web49_section_t mod); 41 | void web49_writebin_module(web49_writebin_buf_t *out, web49_module_t mod); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/write_wat.h: -------------------------------------------------------------------------------- 1 | 2 | #if !defined(WEB49_HEADER_WRITEWAT) 3 | #define WEB49_HEADER_WRITEWAT 4 | 5 | #include "./ast.h" 6 | #include "./io.h" 7 | 8 | void web49_wat_print_lang_type(web49_io_output_t *out, web49_tag_t ltype); 9 | void web49_wat_print_instr(web49_io_output_t *out, web49_instr_t instr); 10 | void web49_wat_print_instr_depth(web49_io_output_t *out, web49_instr_t instr, uint64_t indent); 11 | void web49_wat_print_section_custom(web49_io_output_t *out, web49_module_t mod, web49_section_custom_t scustom); 12 | void web49_wat_print_section_type(web49_io_output_t *out, web49_module_t mod, web49_section_type_t stype); 13 | void web49_wat_print_section_import(web49_io_output_t *out, web49_module_t mod, web49_section_import_t simport); 14 | void web49_wat_print_section_function(web49_io_output_t *out, web49_module_t mod, web49_section_function_t sfunction); 15 | void web49_wat_print_section_table(web49_io_output_t *out, web49_module_t mod, web49_section_table_t stable); 16 | void web49_wat_print_section_memory(web49_io_output_t *out, web49_module_t mod, web49_section_memory_t smemory); 17 | void web49_wat_print_section_global(web49_io_output_t *out, web49_module_t mod, web49_section_global_t sglobal); 18 | void web49_wat_print_section_export(web49_io_output_t *out, web49_module_t mod, web49_section_export_t sexport); 19 | void web49_wat_print_section_start(web49_io_output_t *out, web49_module_t mod, web49_section_start_t sstart); 20 | void web49_wat_print_section_element(web49_io_output_t *out, web49_module_t mod, web49_section_element_t selement); 21 | void web49_wat_print_section_code(web49_io_output_t *out, web49_module_t mod, web49_section_code_t scode); 22 | void web49_wat_print_section_data(web49_io_output_t *out, web49_module_t mod, web49_section_data_t sdata); 23 | void web49_wat_print_section(web49_io_output_t *out, web49_module_t mod, web49_section_t section); 24 | void web49_wat_print_module(web49_io_output_t *out, web49_module_t mod); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /test/bench/.gitignore: -------------------------------------------------------------------------------- 1 | *.time 2 | *.txt 3 | *.wasm 4 | *.out 5 | *.err 6 | *.png -------------------------------------------------------------------------------- /test/bench/binary-trees.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | typedef struct tree_node { 7 | struct tree_node *left_Node, *right_Node; 8 | } tree_node; 9 | 10 | static tree_node *create_Tree(const uint32_t tree_Depth) { 11 | tree_node *const root_Node = malloc(sizeof(tree_node)); 12 | if (root_Node == NULL) { 13 | printf("out of memory at %" PRIu32 ", memory:%" PRIu32 "\n", tree_Depth, 14 | #ifdef __wasm__ 15 | (uint32_t)__builtin_wasm_memory_size(0) 16 | #else 17 | 0 18 | #endif 19 | ); 20 | return root_Node; 21 | } 22 | 23 | if (tree_Depth > 0) { 24 | root_Node->left_Node = create_Tree(tree_Depth - 1); 25 | root_Node->right_Node = create_Tree(tree_Depth - 1); 26 | } else { 27 | root_Node->left_Node = root_Node->right_Node = NULL; 28 | } 29 | 30 | return root_Node; 31 | } 32 | 33 | static void delete_Tree(tree_node *root) { 34 | if (root) { 35 | delete_Tree(root->left_Node); 36 | delete_Tree(root->right_Node); 37 | free(root); 38 | } 39 | } 40 | 41 | static uint32_t compute_Tree_Checksum(const tree_node *const root_Node) { 42 | if (root_Node->left_Node && root_Node->right_Node) 43 | return compute_Tree_Checksum(root_Node->left_Node) + 44 | compute_Tree_Checksum(root_Node->right_Node) + 1; 45 | 46 | return 1; 47 | } 48 | 49 | int main(int argc, char *argv[]) { 50 | const uint32_t minimum_Tree_Depth = 4, 51 | maximum_Tree_Depth = atoi(argv[1]) < minimum_Tree_Depth + 2 52 | ? minimum_Tree_Depth + 2 53 | : atoi(argv[1]); 54 | tree_node *stretch_Tree = create_Tree(maximum_Tree_Depth + 1); 55 | printf("stretch tree of depth %" PRIu32 "\t check: %" PRIu32 "\n", 56 | maximum_Tree_Depth + 1, compute_Tree_Checksum(stretch_Tree)); 57 | delete_Tree(stretch_Tree); 58 | 59 | tree_node *long_Lived_Tree; 60 | 61 | uint32_t long_Lived_Tree_Checksum, 62 | tree_Checksums[(maximum_Tree_Depth - minimum_Tree_Depth + 2) / 2]; 63 | { 64 | { 65 | long_Lived_Tree = create_Tree(maximum_Tree_Depth); 66 | long_Lived_Tree_Checksum = compute_Tree_Checksum(long_Lived_Tree); 67 | } 68 | 69 | for (uint32_t tree_Depth = minimum_Tree_Depth; 70 | tree_Depth <= maximum_Tree_Depth; tree_Depth += 2) { 71 | uint32_t total_Trees_Checksum = 0; 72 | for (uint32_t iterations = 73 | 1 << (maximum_Tree_Depth - tree_Depth + minimum_Tree_Depth); 74 | iterations-- > 0;) { 75 | tree_node *temp_Tree = create_Tree(tree_Depth); 76 | total_Trees_Checksum += compute_Tree_Checksum(temp_Tree); 77 | delete_Tree(temp_Tree); 78 | } 79 | 80 | tree_Checksums[(tree_Depth - minimum_Tree_Depth) / 2] = 81 | total_Trees_Checksum; 82 | } 83 | 84 | delete_Tree(long_Lived_Tree); 85 | } 86 | 87 | for (uint32_t tree_Depth = minimum_Tree_Depth; 88 | tree_Depth <= maximum_Tree_Depth; tree_Depth += 2) 89 | printf("%" PRIu32 "\t trees of depth %" PRIu32 "\t check: %" PRIu32 "\n", 90 | 1 << (maximum_Tree_Depth - tree_Depth + minimum_Tree_Depth), 91 | tree_Depth, tree_Checksums[(tree_Depth - minimum_Tree_Depth) / 2]); 92 | 93 | printf("long lived tree of depth %" PRIu32 " \t check: %" PRIu32 " \n", 94 | maximum_Tree_Depth, long_Lived_Tree_Checksum); 95 | 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /test/bench/fannkuch-redux.c: -------------------------------------------------------------------------------- 1 | #define PREFERRED_NUMBER_OF_BLOCKS_TO_USE 12 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char **argv) { 8 | const int n = atoi(argv[1]); 9 | 10 | int factorial_Lookup_Table[n + 1]; 11 | factorial_Lookup_Table[0] = 1; 12 | for (int i = 0; ++i <= n;) { 13 | factorial_Lookup_Table[i] = i * factorial_Lookup_Table[i - 1]; 14 | } 15 | 16 | const int block_Size = 17 | factorial_Lookup_Table[n] / 18 | (factorial_Lookup_Table[n] < PREFERRED_NUMBER_OF_BLOCKS_TO_USE 19 | ? 1 20 | : PREFERRED_NUMBER_OF_BLOCKS_TO_USE); 21 | 22 | int maximum_Flip_Count = 0, checksum = 0; 23 | 24 | #pragma omp parallel for reduction(max : maximum_Flip_Count) reduction(+ : checksum) 25 | for (int initial_Permutation_Index_For_Block = 0; 26 | initial_Permutation_Index_For_Block < factorial_Lookup_Table[n]; 27 | initial_Permutation_Index_For_Block += block_Size) { 28 | int count[n]; 29 | int8_t temp_Permutation[n], current_Permutation[n]; 30 | 31 | count[0] = 0; 32 | for (int i = 0; i < n; ++i) 33 | current_Permutation[i] = i; 34 | for (int i = n - 1, permutation_Index = initial_Permutation_Index_For_Block; 35 | i > 0; --i) { 36 | const int d = permutation_Index / factorial_Lookup_Table[i]; 37 | permutation_Index = permutation_Index % factorial_Lookup_Table[i]; 38 | count[i] = d; 39 | 40 | for (int j = 0; j < n; ++j) 41 | temp_Permutation[j] = current_Permutation[j]; 42 | for (int j = 0; j <= i; ++j) 43 | current_Permutation[j] = j + d <= i ? temp_Permutation[j + d] 44 | : temp_Permutation[j + d - i - 1]; 45 | } 46 | 47 | const int last_Permutation_Index_In_Block = 48 | initial_Permutation_Index_For_Block + block_Size - 1; 49 | for (int permutation_Index = initial_Permutation_Index_For_Block;; 50 | ++permutation_Index) { 51 | if (current_Permutation[0] > 0) { 52 | for (int i = 0; ++i < n;) { 53 | temp_Permutation[i] = current_Permutation[i]; 54 | } 55 | 56 | int flip_Count = 1; 57 | 58 | for (int first_Value = current_Permutation[0]; 59 | temp_Permutation[first_Value] > 0; ++flip_Count) { 60 | const int8_t new_First_Value = temp_Permutation[first_Value]; 61 | temp_Permutation[first_Value] = first_Value; 62 | 63 | if (first_Value > 2) { 64 | int low_Index = 1, high_Index = first_Value - 1; 65 | do { 66 | const int8_t temp = temp_Permutation[high_Index]; 67 | temp_Permutation[high_Index] = temp_Permutation[low_Index]; 68 | temp_Permutation[low_Index] = temp; 69 | } while (low_Index++ + 3 <= high_Index-- && low_Index < 16); 70 | } 71 | 72 | first_Value = new_First_Value; 73 | } 74 | 75 | if (permutation_Index % 2 == 0) { 76 | checksum += flip_Count; 77 | } else { 78 | checksum -= flip_Count; 79 | } 80 | 81 | if (flip_Count > maximum_Flip_Count) 82 | maximum_Flip_Count = flip_Count; 83 | } 84 | 85 | if (permutation_Index >= last_Permutation_Index_In_Block) { 86 | break; 87 | } 88 | 89 | int8_t first_Value = current_Permutation[1]; 90 | current_Permutation[1] = current_Permutation[0]; 91 | current_Permutation[0] = first_Value; 92 | for (int i = 1; ++count[i] > i;) { 93 | count[i++] = 0; 94 | const int8_t new_First_Value = current_Permutation[0] = 95 | current_Permutation[1]; 96 | 97 | for (int j = 0; ++j < i;) { 98 | current_Permutation[j] = current_Permutation[j + 1]; 99 | } 100 | 101 | current_Permutation[i] = first_Value; 102 | first_Value = new_First_Value; 103 | } 104 | } 105 | } 106 | 107 | printf("%d\nPfannkuchen(%d) = %d\n", checksum, n, maximum_Flip_Count); 108 | 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /test/bench/fib_f32.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | float fib(float n) { 5 | if (n < 2) { 6 | return n; 7 | } else { 8 | return fib(n - 2) + fib(n - 1); 9 | } 10 | } 11 | 12 | int main(int argc, const char **argv) { 13 | printf("%f\n", fib(40)); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /test/bench/fib_f64.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | double fib(double n) { 5 | if (n < 2) { 6 | return n; 7 | } else { 8 | return fib(n - 2) + fib(n - 1); 9 | } 10 | } 11 | 12 | int main(int argc, const char **argv) { 13 | printf("%lf\n", fib(40)); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /test/bench/fib_i32.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | uint64_t fib(uint64_t n) { 8 | if (n < 2) { 9 | return n; 10 | } else { 11 | return fib(n - 2) + fib(n - 1); 12 | } 13 | } 14 | 15 | int main(int argc, char **argv) { 16 | uint32_t fibn = fib(40); 17 | printf("fib(40) = %"PRIu32"\n", fibn); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /test/bench/fib_i64.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | uint64_t fib(uint64_t n) { 8 | if (n < 2) { 9 | return n; 10 | } else { 11 | return fib(n - 2) + fib(n - 1); 12 | } 13 | } 14 | 15 | int main(int argc, char **argv) { 16 | uint64_t fibn = fib(40); 17 | printf("fib(40) = %"PRIu64"\n", fibn); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /test/bench/mandelbrot-simd.c: -------------------------------------------------------------------------------- 1 | #define LIMIT_SQUARED 4.0 2 | #define MAXIMUM_ITERATIONS 50 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | typedef double doublex2 __attribute__((vector_size(16))); 13 | typedef uint64_t uint64x2_t __attribute__((vector_size(16))); 14 | 15 | static inline void calcSum(doublex2 *r, doublex2 *i, doublex2 *sum, 16 | const doublex2 init_r[4], const doublex2 init_i) { 17 | for (uint64_t x_Minor = 0; x_Minor < 4; x_Minor++) { 18 | doublex2 r2 = r[x_Minor] * r[x_Minor]; 19 | doublex2 i2 = i[x_Minor] * i[x_Minor]; 20 | doublex2 ri = r[x_Minor] * i[x_Minor]; 21 | 22 | sum[x_Minor] = r2 + i2; 23 | 24 | r[x_Minor] = r2 - i2 + init_r[x_Minor]; 25 | i[x_Minor] = ri + ri + init_i; 26 | } 27 | } 28 | 29 | static inline bool vec_gt(const doublex2 *v) { 30 | const doublex2 f = {LIMIT_SQUARED, LIMIT_SQUARED}; 31 | const uint64x2_t r = (v[0] > f) & (v[1] > f) & (v[2] > f) & (v[3] > f); 32 | return r[0] && r[1]; 33 | } 34 | 35 | static inline uint8_t clrPixels_gt(const doublex2 *v) { 36 | const doublex2 f = {LIMIT_SQUARED, LIMIT_SQUARED}; 37 | const uint64x2_t r0 = v[0] <= f; 38 | const uint64x2_t r1 = v[1] <= f; 39 | const uint64x2_t r2 = v[2] <= f; 40 | const uint64x2_t r3 = v[3] <= f; 41 | return (r0[0] & 0x1) << 7 | (r0[1] & 0x1) << 6 | (r1[0] & 0x1) << 5 | 42 | (r1[1] & 0x1) << 4 | (r2[0] & 0x1) << 3 | (r2[1] & 0x1) << 2 | 43 | (r3[0] & 0x1) << 1 | (r3[1] & 0x1) << 0; 44 | } 45 | 46 | static inline uint8_t mand8(const doublex2 init_r[4], const doublex2 init_i) { 47 | doublex2 pixel_Group_r[4], pixel_Group_i[4]; 48 | for (uint64_t x_Minor = 0; x_Minor < 4; x_Minor++) { 49 | pixel_Group_r[x_Minor] = init_r[x_Minor]; 50 | pixel_Group_i[x_Minor] = init_i; 51 | } 52 | 53 | doublex2 sum[4]; 54 | for (unsigned j = 0; j < 6; j++) { 55 | for (unsigned k = 0; k < 8; k++) { 56 | calcSum(pixel_Group_r, pixel_Group_i, sum, init_r, init_i); 57 | } 58 | if (vec_gt(sum)) { 59 | return 0x00; 60 | } 61 | } 62 | calcSum(pixel_Group_r, pixel_Group_i, sum, init_r, init_i); 63 | calcSum(pixel_Group_r, pixel_Group_i, sum, init_r, init_i); 64 | return clrPixels_gt(sum); 65 | } 66 | 67 | static inline uint64_t mand64(const doublex2 init_r[4], const doublex2 init_i) { 68 | uint64_t sixtyfour_Pixels = 0; 69 | for (uint64_t byte = 0; byte < 8; byte++) { 70 | const uint64_t eight_Pixels = mand8(init_r + 4 * byte, init_i); 71 | sixtyfour_Pixels = 72 | (sixtyfour_Pixels >> UINT64_C(8)) | (eight_Pixels << UINT64_C(56)); 73 | } 74 | return sixtyfour_Pixels; 75 | } 76 | 77 | int main(int argc, char **argv) { 78 | const uint64_t image_Width_And_Height = 79 | (__builtin_expect(atoi(argv[1]), 15000) + 7) / 8 * 8; 80 | 81 | uint8_t *const pixels = 82 | malloc(image_Width_And_Height * image_Width_And_Height / 8); 83 | 84 | doublex2 initial_r[image_Width_And_Height / 2]; 85 | double initial_i[image_Width_And_Height]; 86 | for (uint64_t xy = 0; xy < image_Width_And_Height; xy++) { 87 | initial_r[xy / 2] = 88 | 2.0 / image_Width_And_Height * (doublex2){xy, xy + 1} - 1.5; 89 | initial_i[xy] = 2.0 / image_Width_And_Height * xy - 1.0; 90 | } 91 | 92 | if (image_Width_And_Height % 64) { 93 | // process 8 pixels (one byte) at a time 94 | for (uint64_t y = 0; y < image_Width_And_Height; y++) { 95 | const doublex2 prefetched_Initial_i = {initial_i[y], initial_i[y]}; 96 | const size_t rowStart = y * image_Width_And_Height / 8; 97 | for (uint64_t x_Major = 0; x_Major < image_Width_And_Height; 98 | x_Major += 8) { 99 | const doublex2 *prefetched_Initial_r = &initial_r[x_Major / 2]; 100 | pixels[rowStart + x_Major / 8] = 101 | mand8(prefetched_Initial_r, prefetched_Initial_i); 102 | } 103 | } 104 | } else { 105 | // process 64 pixels (8 bytes) at a time 106 | for (uint64_t y = 0; y < image_Width_And_Height; y++) { 107 | const doublex2 prefetched_Initial_i = {initial_i[y], initial_i[y]}; 108 | const size_t rowStart = y * image_Width_And_Height / 8; 109 | for (uint64_t x_Major = 0; x_Major < image_Width_And_Height; 110 | x_Major += 8) { 111 | const doublex2 *prefetched_Initial_r = &initial_r[x_Major / 2]; 112 | const uint64_t sixtyfour_Pixels = 113 | mand64(prefetched_Initial_r, prefetched_Initial_i); 114 | memcpy(&pixels[rowStart + x_Major / 8], &sixtyfour_Pixels, 8); 115 | } 116 | } 117 | } 118 | 119 | fprintf(stdout, "P4\n%" PRIu64 " %" PRIu64 "\n", image_Width_And_Height, 120 | image_Width_And_Height); 121 | fwrite(pixels, image_Width_And_Height * image_Width_And_Height / 8, 1, 122 | stdout); 123 | 124 | free(pixels); 125 | 126 | return 0; 127 | } 128 | -------------------------------------------------------------------------------- /test/bench/mandelbrot.c: -------------------------------------------------------------------------------- 1 | #define LIMIT_SQUARED 4.0 2 | #define MAXIMUM_ITERATIONS 50 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main(int argc, char **argv) { 10 | const uint64_t image_Width_And_Height = 11 | (__builtin_expect(atoi(argv[1]), 15000) + 7) / 8 * 8; 12 | 13 | uint8_t *const pixels = 14 | malloc(image_Width_And_Height * image_Width_And_Height / 8); 15 | 16 | double initial_r[image_Width_And_Height], initial_i[image_Width_And_Height]; 17 | for (uint64_t xy = 0; xy < image_Width_And_Height; xy++) { 18 | initial_r[xy] = 2.0 / image_Width_And_Height * xy - 1.5; 19 | initial_i[xy] = 2.0 / image_Width_And_Height * xy - 1.0; 20 | } 21 | 22 | for (uint64_t y = 0; y < image_Width_And_Height; y++) { 23 | const double prefetched_Initial_i = initial_i[y]; 24 | for (uint64_t x_Major = 0; x_Major < image_Width_And_Height; x_Major += 8) { 25 | double pixel_Group_r[8], pixel_Group_i[8]; 26 | for (uint64_t x_Minor = 0; x_Minor < 8; x_Minor++) { 27 | pixel_Group_r[x_Minor] = initial_r[x_Major + x_Minor]; 28 | pixel_Group_i[x_Minor] = prefetched_Initial_i; 29 | } 30 | 31 | uint8_t eight_Pixels = 0xff; 32 | 33 | int iteration = MAXIMUM_ITERATIONS; 34 | do { 35 | uint8_t current_Pixel_Bitmask = 0x80; 36 | for (uint64_t x_Minor = 0; x_Minor < 8; x_Minor++) { 37 | const double r = pixel_Group_r[x_Minor]; 38 | const double i = pixel_Group_i[x_Minor]; 39 | 40 | pixel_Group_r[x_Minor] = r * r - i * i + initial_r[x_Major + x_Minor]; 41 | pixel_Group_i[x_Minor] = 2.0 * r * i + prefetched_Initial_i; 42 | 43 | if (r * r + i * i > LIMIT_SQUARED) 44 | eight_Pixels &= ~current_Pixel_Bitmask; 45 | 46 | current_Pixel_Bitmask >>= 1; 47 | } 48 | } while (eight_Pixels && --iteration); 49 | 50 | pixels[y * image_Width_And_Height / 8 + x_Major / 8] = eight_Pixels; 51 | } 52 | } 53 | 54 | fprintf(stdout, "P4\n%" PRIu64 " %" PRIu64 "\n", image_Width_And_Height, 55 | image_Width_And_Height); 56 | fwrite(pixels, image_Width_And_Height * image_Width_And_Height / 8, 1, 57 | stdout); 58 | 59 | free(pixels); 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /test/bench/nbody.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | typedef struct { 8 | double position[3], velocity[3], mass; 9 | } body; 10 | 11 | #define SOLAR_MASS (4 * M_PI * M_PI) 12 | #define DAYS_PER_YEAR 365.24 13 | #define BODIES_COUNT 5 14 | 15 | static body solar_Bodies[] = { 16 | {// Sun 17 | .mass = SOLAR_MASS}, 18 | {// Jupiter 19 | {4.84143144246472090e+00, -1.16032004402742839e+00, 20 | -1.03622044471123109e-01}, 21 | {1.66007664274403694e-03 * DAYS_PER_YEAR, 22 | 7.69901118419740425e-03 * DAYS_PER_YEAR, 23 | -6.90460016972063023e-05 * DAYS_PER_YEAR}, 24 | 9.54791938424326609e-04 * SOLAR_MASS}, 25 | {// Saturn 26 | {8.34336671824457987e+00, 4.12479856412430479e+00, 27 | -4.03523417114321381e-01}, 28 | {-2.76742510726862411e-03 * DAYS_PER_YEAR, 29 | 4.99852801234917238e-03 * DAYS_PER_YEAR, 30 | 2.30417297573763929e-05 * DAYS_PER_YEAR}, 31 | 2.85885980666130812e-04 * SOLAR_MASS}, 32 | {// Uranus 33 | {1.28943695621391310e+01, -1.51111514016986312e+01, 34 | -2.23307578892655734e-01}, 35 | {2.96460137564761618e-03 * DAYS_PER_YEAR, 36 | 2.37847173959480950e-03 * DAYS_PER_YEAR, 37 | -2.96589568540237556e-05 * DAYS_PER_YEAR}, 38 | 4.36624404335156298e-05 * SOLAR_MASS}, 39 | {// Neptune 40 | {1.53796971148509165e+01, -2.59193146099879641e+01, 41 | 1.79258772950371181e-01}, 42 | {2.68067772490389322e-03 * DAYS_PER_YEAR, 43 | 1.62824170038242295e-03 * DAYS_PER_YEAR, 44 | -9.51592254519715870e-05 * DAYS_PER_YEAR}, 45 | 5.15138902046611451e-05 * SOLAR_MASS}}; 46 | 47 | static void advance(body bodies[]) { 48 | #define INTERACTIONS_COUNT (BODIES_COUNT * (BODIES_COUNT - 1) / 2) 49 | 50 | static double position_Deltas[3][INTERACTIONS_COUNT], 51 | magnitudes[INTERACTIONS_COUNT]; 52 | 53 | for (unsigned int i = 0, k = 0; i < BODIES_COUNT - 1; ++i) 54 | for (unsigned int j = i + 1; j < BODIES_COUNT; ++j, ++k) 55 | for (unsigned int m = 0; m < 3; ++m) 56 | position_Deltas[m][k] = bodies[i].position[m] - bodies[j].position[m]; 57 | 58 | for (unsigned int i = 0; i < INTERACTIONS_COUNT; ++i) { 59 | const double dx = position_Deltas[0][i]; 60 | const double dy = position_Deltas[1][i]; 61 | const double dz = position_Deltas[2][i]; 62 | const double distance_Squared = dx * dx + dy * dy + dz * dz; 63 | double distance = sqrt(distance_Squared); 64 | magnitudes[i] = 0.01 / (distance_Squared * distance); 65 | } 66 | 67 | for (unsigned int i = 0, k = 0; i < BODIES_COUNT - 1; ++i) 68 | for (unsigned int j = i + 1; j < BODIES_COUNT; ++j, ++k) { 69 | const double i_mass_magnitude = bodies[i].mass * magnitudes[k], 70 | j_mass_magnitude = bodies[j].mass * magnitudes[k]; 71 | for (unsigned int m = 0; m < 3; ++m) { 72 | bodies[i].velocity[m] -= position_Deltas[m][k] * j_mass_magnitude; 73 | bodies[j].velocity[m] += position_Deltas[m][k] * i_mass_magnitude; 74 | } 75 | } 76 | 77 | for (unsigned int i = 0; i < BODIES_COUNT; ++i) 78 | for (unsigned int m = 0; m < 3; ++m) 79 | bodies[i].position[m] += 0.01 * bodies[i].velocity[m]; 80 | } 81 | 82 | static void offset_Momentum(body bodies[]) { 83 | for (unsigned int i = 0; i < BODIES_COUNT; ++i) 84 | for (unsigned int m = 0; m < 3; ++m) 85 | bodies[0].velocity[m] -= 86 | bodies[i].velocity[m] * bodies[i].mass / SOLAR_MASS; 87 | } 88 | 89 | static void output_Energy(body bodies[]) { 90 | double energy = 0; 91 | for (unsigned int i = 0; i < BODIES_COUNT; ++i) { 92 | energy += 0.5 * bodies[i].mass * 93 | (bodies[i].velocity[0] * bodies[i].velocity[0] + 94 | bodies[i].velocity[1] * bodies[i].velocity[1] + 95 | bodies[i].velocity[2] * bodies[i].velocity[2]); 96 | 97 | for (unsigned int j = i + 1; j < BODIES_COUNT; ++j) { 98 | double position_Delta[3]; 99 | for (unsigned int m = 0; m < 3; ++m) 100 | position_Delta[m] = bodies[i].position[m] - bodies[j].position[m]; 101 | 102 | energy -= bodies[i].mass * bodies[j].mass / 103 | sqrt(position_Delta[0] * position_Delta[0] + 104 | position_Delta[1] * position_Delta[1] + 105 | position_Delta[2] * position_Delta[2]); 106 | } 107 | } 108 | 109 | printf("%.9f\n", energy); 110 | } 111 | 112 | int main(int argc, char *argv[]) { 113 | offset_Momentum(solar_Bodies); 114 | output_Energy(solar_Bodies); 115 | for (int n = atoi(argv[1]); n--; advance(solar_Bodies)) 116 | ; 117 | output_Energy(solar_Bodies); 118 | } 119 | -------------------------------------------------------------------------------- /test/bench/nbody.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | static constexpr const double PI = 3.141592653589793; 7 | static constexpr const double SOLAR_MASS = 4 * PI * PI; 8 | static constexpr const double DAYS_PER_YEAR = 365.24; 9 | 10 | class Body { 11 | public: 12 | double x, vx, y, vy, z, vz; 13 | double mass; 14 | 15 | Body &offsetMomentum(const double px, const double py, 16 | const double pz) noexcept { 17 | vx = -px / SOLAR_MASS; 18 | vy = -py / SOLAR_MASS; 19 | vz = -pz / SOLAR_MASS; 20 | return *this; 21 | } 22 | }; 23 | 24 | constexpr Body jupiter() { 25 | return Body{/*x =*/4.84143144246472090e+00, 26 | /*vx =*/1.66007664274403694e-03 * DAYS_PER_YEAR, 27 | /*y =*/-1.16032004402742839e+00, 28 | /*vy =*/7.69901118419740425e-03 * DAYS_PER_YEAR, 29 | /*z =*/-1.03622044471123109e-01, 30 | /*vz =*/-6.90460016972063023e-05 * DAYS_PER_YEAR, 31 | /*mass =*/9.54791938424326609e-04 * SOLAR_MASS}; 32 | } 33 | 34 | constexpr Body saturn() { 35 | return Body{/*x = */ 8.34336671824457987e+00, 36 | /*vx = */ -2.76742510726862411e-03 * DAYS_PER_YEAR, 37 | /*y = */ 4.12479856412430479e+00, 38 | /*vy = */ 4.99852801234917238e-03 * DAYS_PER_YEAR, 39 | /*z = */ -4.03523417114321381e-01, 40 | /*vz = */ 2.30417297573763929e-05 * DAYS_PER_YEAR, 41 | /*mass =*/2.85885980666130812e-04 * SOLAR_MASS}; 42 | } 43 | 44 | constexpr Body uranus() { 45 | return Body{/*x =*/1.28943695621391310e+01, 46 | /*vx = */ 2.96460137564761618e-03 * DAYS_PER_YEAR, 47 | /*y =*/-1.51111514016986312e+01, 48 | /*vy = */ 2.37847173959480950e-03 * DAYS_PER_YEAR, 49 | /*z =*/-2.23307578892655734e-01, 50 | /*vz = */ -2.96589568540237556e-05 * DAYS_PER_YEAR, 51 | /*mass =*/4.36624404335156298e-05 * SOLAR_MASS}; 52 | } 53 | 54 | constexpr Body neptune() { 55 | return Body{/*x = */ 1.53796971148509165e+01, 56 | /*vx = */ 2.68067772490389322e-03 * DAYS_PER_YEAR, 57 | /*y = */ -2.59193146099879641e+01, 58 | /*vy = */ 1.62824170038242295e-03 * DAYS_PER_YEAR, 59 | /*z = */ 1.79258772950371181e-01, 60 | /*vz = */ -9.51592254519715870e-05 * DAYS_PER_YEAR, 61 | /*mass = */ 5.15138902046611451e-05 * SOLAR_MASS}; 62 | } 63 | 64 | constexpr Body sun() { 65 | return Body{/*x = */ 0, 66 | /*vx = */ 0, 67 | /*y = */ 0, 68 | /*vy = */ 0, 69 | /*z = */ 0, 70 | /*vz = */ 0, 71 | /*mass = */ SOLAR_MASS}; 72 | } 73 | 74 | class NBodySystem { 75 | private: 76 | std::array bodies; 77 | static constexpr unsigned int bodies_size = 5; 78 | 79 | public: 80 | NBodySystem() noexcept 81 | : bodies{{sun(), jupiter(), saturn(), uranus(), neptune()}} { 82 | double px = 0.0; 83 | double py = 0.0; 84 | double pz = 0.0; 85 | for (unsigned i = 0; i != bodies_size; ++i) { 86 | px += bodies[i].vx * bodies[i].mass; 87 | py += bodies[i].vy * bodies[i].mass; 88 | pz += bodies[i].vz * bodies[i].mass; 89 | } 90 | bodies[0].offsetMomentum(px, py, pz); 91 | } 92 | 93 | void advance(const double dt) noexcept { 94 | constexpr const unsigned N = ((bodies_size - 1) * bodies_size) / 2; 95 | static double Rdx[N], Rdy[N], Rdz[N]; 96 | static double mag[N]; 97 | 98 | for (unsigned int i = 0, k = 0; i != bodies_size - 1; ++i) { 99 | for (unsigned int j = i + 1; j != bodies_size; ++j, ++k) { 100 | Rdx[k] = bodies[i].x - bodies[j].x; 101 | Rdy[k] = bodies[i].y - bodies[j].y; 102 | Rdz[k] = bodies[i].z - bodies[j].z; 103 | } 104 | } 105 | 106 | for (unsigned int i = 0; i != N; ++i) { 107 | const double dx = Rdx[i]; 108 | const double dy = Rdy[i]; 109 | const double dz = Rdz[i]; 110 | const double dSquared = dx*dx + dy*dy + dz*dz; 111 | double distance = sqrt(dSquared); 112 | const double dmag = dt / (dSquared * distance); 113 | mag[i] = dmag; 114 | } 115 | 116 | for (unsigned int i = 0, k = 0; i != bodies_size - 1; ++i) { 117 | Body &iBody = bodies[i]; 118 | for (unsigned int j = i + 1; j != bodies_size; ++j, ++k) { 119 | Body &jBody = bodies[j]; 120 | double const jmm = jBody.mass * mag[k]; 121 | iBody.vx -= Rdx[k] * jmm; 122 | iBody.vy -= Rdy[k] * jmm; 123 | iBody.vz -= Rdz[k] * jmm; 124 | 125 | double const imm = iBody.mass * mag[k]; 126 | jBody.vx += Rdx[k] * imm; 127 | jBody.vy += Rdy[k] * imm; 128 | jBody.vz += Rdz[k] * imm; 129 | } 130 | } 131 | 132 | for (unsigned int i = 0; i != bodies_size; ++i) { 133 | Body &iBody = bodies[i]; 134 | iBody.x += dt * iBody.vx; 135 | iBody.y += dt * iBody.vy; 136 | iBody.z += dt * iBody.vz; 137 | } 138 | } 139 | 140 | double energy() noexcept { 141 | double e = 0.0; 142 | 143 | for (unsigned int i = 0; i != bodies_size; ++i) { 144 | Body const iBody = bodies[i]; 145 | e += 0.5 * iBody.mass * 146 | (iBody.vx * iBody.vx + iBody.vy * iBody.vy + iBody.vz * iBody.vz); 147 | 148 | for (unsigned int j = i + 1; j != bodies_size; ++j) { 149 | Body const &jBody = bodies[j]; 150 | 151 | const double dx = iBody.x - jBody.x; 152 | const double dy = iBody.y - jBody.y; 153 | const double dz = iBody.z - jBody.z; 154 | 155 | const double distance = sqrt(dx * dx + dy * dy + dz * dz); 156 | e -= (iBody.mass * jBody.mass) / distance; 157 | } 158 | } 159 | return e; 160 | } 161 | }; 162 | 163 | int main(int argc, char **argv) { 164 | std::ios_base::sync_with_stdio(false); 165 | int n = std::atoi(argv[1]); 166 | 167 | NBodySystem bodies; 168 | std::cout << std::setprecision(9) << bodies.energy() << std::endl; 169 | for (int i = 0; i < n; ++i) 170 | bodies.advance(0.01); 171 | std::cout << bodies.energy() << '\n'; 172 | } 173 | -------------------------------------------------------------------------------- /test/bench/nop.c: -------------------------------------------------------------------------------- 1 | int main(int argc, char *argv[]) {} 2 | -------------------------------------------------------------------------------- /test/bench/trap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | int *x = (int*) (SIZE_MAX); 7 | return *x; 8 | } -------------------------------------------------------------------------------- /test/core/comments.wast: -------------------------------------------------------------------------------- 1 | ;; Test comment syntax 2 | 3 | ;;comment 4 | 5 | ;;;;;;;;;;; 6 | 7 | ;;comment 8 | 9 | ( ;;comment 10 | module;;comment 11 | );;comment 12 | 13 | ;;) 14 | ;;;) 15 | ;; ;) 16 | ;; (; 17 | 18 | (;;) 19 | 20 | (;comment;) 21 | 22 | (;;comment;) 23 | 24 | (;;;comment;) 25 | 26 | (;;;;;;;;;;;;;;) 27 | 28 | (;(((((((((( ;) 29 | 30 | (;)))))))))));) 31 | 32 | (;comment";) 33 | 34 | (;comment"";) 35 | 36 | (;comment""";) 37 | 38 | ;; ASCII 00-1F, 7F 39 | (; 40 | ;) 41 | 42 | ;; null-byte followed immediately by end-of-comment delimiter 43 | (;;) 44 | 45 | 46 | (;Heiße Würstchen;) 47 | 48 | (;;) 49 | 50 | (;comment 51 | comment;) 52 | 53 | (;comment;) 54 | 55 | (;comment;)((;comment;) 56 | (;comment;)module(;comment;) 57 | (;comment;))(;comment;) 58 | 59 | (;comment(;nested;)comment;) 60 | 61 | (;comment 62 | (;nested 63 | ;)comment 64 | ;) 65 | 66 | (module 67 | (;comment(;nested(;further;)nested;)comment;) 68 | ) 69 | 70 | (;comment;;comment;) 71 | 72 | (;comment;;comment 73 | ;) 74 | 75 | (module 76 | (;comment;;comment(;nested;)comment;) 77 | ) 78 | -------------------------------------------------------------------------------- /test/core/custom.wast: -------------------------------------------------------------------------------- 1 | (module binary 2 | "\00asm" "\01\00\00\00" 3 | "\00\24\10" "a custom section" "this is the payload" 4 | "\00\20\10" "a custom section" "this is payload" 5 | "\00\11\10" "a custom section" "" 6 | "\00\10\00" "" "this is payload" 7 | "\00\01\00" "" "" 8 | "\00\24\10" "\00\00custom sectio\00" "this is the payload" 9 | "\00\24\10" "\ef\bb\bfa custom sect" "this is the payload" 10 | "\00\24\10" "a custom sect\e2\8c\a3" "this is the payload" 11 | "\00\1f\16" "module within a module" "\00asm" "\01\00\00\00" 12 | ) 13 | 14 | (module binary 15 | "\00asm" "\01\00\00\00" 16 | "\00\0e\06" "custom" "payload" 17 | "\00\0e\06" "custom" "payload" 18 | "\01\01\00" ;; type section 19 | "\00\0e\06" "custom" "payload" 20 | "\00\0e\06" "custom" "payload" 21 | "\02\01\00" ;; import section 22 | "\00\0e\06" "custom" "payload" 23 | "\00\0e\06" "custom" "payload" 24 | "\03\01\00" ;; function section 25 | "\00\0e\06" "custom" "payload" 26 | "\00\0e\06" "custom" "payload" 27 | "\04\01\00" ;; table section 28 | "\00\0e\06" "custom" "payload" 29 | "\00\0e\06" "custom" "payload" 30 | "\05\01\00" ;; memory section 31 | "\00\0e\06" "custom" "payload" 32 | "\00\0e\06" "custom" "payload" 33 | "\06\01\00" ;; global section 34 | "\00\0e\06" "custom" "payload" 35 | "\00\0e\06" "custom" "payload" 36 | "\07\01\00" ;; export section 37 | "\00\0e\06" "custom" "payload" 38 | "\00\0e\06" "custom" "payload" 39 | "\09\01\00" ;; element section 40 | "\00\0e\06" "custom" "payload" 41 | "\00\0e\06" "custom" "payload" 42 | "\0a\01\00" ;; code section 43 | "\00\0e\06" "custom" "payload" 44 | "\00\0e\06" "custom" "payload" 45 | "\0b\01\00" ;; data section 46 | "\00\0e\06" "custom" "payload" 47 | "\00\0e\06" "custom" "payload" 48 | ) 49 | 50 | (module binary 51 | "\00asm" "\01\00\00\00" 52 | "\01\07\01\60\02\7f\7f\01\7f" ;; type section 53 | "\00\1a\06" "custom" "this is the payload" ;; custom section 54 | "\03\02\01\00" ;; function section 55 | "\07\0a\01\06\61\64\64\54\77\6f\00\00" ;; export section 56 | "\0a\09\01\07\00\20\00\20\01\6a\0b" ;; code section 57 | "\00\1b\07" "custom2" "this is the payload" ;; custom section 58 | ) 59 | 60 | (assert_malformed 61 | (module binary 62 | "\00asm" "\01\00\00\00" 63 | "\00" 64 | ) 65 | "unexpected end" 66 | ) 67 | 68 | (assert_malformed 69 | (module binary 70 | "\00asm" "\01\00\00\00" 71 | "\00\00" 72 | ) 73 | "unexpected end" 74 | ) 75 | 76 | (assert_malformed 77 | (module binary 78 | "\00asm" "\01\00\00\00" 79 | "\00\00\00\05\01\00\07\00\00" 80 | ) 81 | "unexpected end" 82 | ) 83 | 84 | (assert_malformed 85 | (module binary 86 | "\00asm" "\01\00\00\00" 87 | "\00\26\10" "a custom section" "this is the payload" 88 | ) 89 | "length out of bounds" 90 | ) 91 | 92 | (assert_malformed 93 | (module binary 94 | "\00asm" "\01\00\00\00" 95 | "\00\25\10" "a custom section" "this is the payload" 96 | "\00\24\10" "a custom section" "this is the payload" 97 | ) 98 | "malformed section id" 99 | ) 100 | 101 | (assert_malformed 102 | (module binary 103 | "\00asm" "\01\00\00\00" 104 | "\01\07\01\60\02\7f\7f\01\7f" ;; type section 105 | "\00\25\10" "a custom section" "this is the payload" ;; wrong length! 106 | "\03\02\01\00" ;; function section 107 | "\0a\09\01\07\00\20\00\20\01\6a\0b" ;; code section 108 | "\00\1b\07" "custom2" "this is the payload" ;; custom section 109 | ) 110 | "function and code section have inconsistent lengths" 111 | ) 112 | 113 | ;; Test concatenated modules. 114 | (assert_malformed 115 | (module binary 116 | "\00asm\01\00\00\00" 117 | "\00asm\01\00\00\00" 118 | ) 119 | "length out of bounds" 120 | ) 121 | 122 | (assert_malformed 123 | (module binary 124 | "\00asm" "\01\00\00\00" 125 | "\05\03\01\00\01" ;; memory section 126 | "\0c\01\02" ;; data count section (2 segments) 127 | "\0b\06\01\00\41\00\0b\00" ;; data section (1 segment) 128 | ) 129 | "data count and data section have inconsistent lengths" 130 | ) 131 | -------------------------------------------------------------------------------- /test/core/exports.wast: -------------------------------------------------------------------------------- 1 | ;; Functions 2 | 3 | (module (func) (export "a" (func 0))) 4 | (module (func) (export "a" (func 0)) (export "b" (func 0))) 5 | (module (func) (func) (export "a" (func 0)) (export "b" (func 1))) 6 | 7 | (module (func (export "a"))) 8 | (module (func (export "a") (export "b") (export "c"))) 9 | (module (func (export "a") (export "b") (param i32))) 10 | (module (func) (export "a" (func 0))) 11 | (module (func $a (export "a"))) 12 | (module (func $a) (export "a" (func $a))) 13 | (module (export "a" (func 0)) (func)) 14 | (module (export "a" (func $a)) (func $a)) 15 | 16 | (module $Func 17 | (export "e" (func $f)) 18 | (func $f (param $n i32) (result i32) 19 | (return (i32.add (local.get $n) (i32.const 1))) 20 | ) 21 | ) 22 | (assert_return (invoke "e" (i32.const 42)) (i32.const 43)) 23 | (assert_return (invoke $Func "e" (i32.const 42)) (i32.const 43)) 24 | (module) 25 | (module $Other1) 26 | (assert_return (invoke $Func "e" (i32.const 42)) (i32.const 43)) 27 | 28 | (module 29 | (type (;0;) (func (result i32))) 30 | (func (;0;) (type 0) (result i32) i32.const 42) 31 | (export "a" (func 0)) 32 | (export "b" (func 0)) 33 | (export "c" (func 0))) 34 | (assert_return (invoke "a") (i32.const 42)) 35 | (assert_return (invoke "b") (i32.const 42)) 36 | (assert_return (invoke "c") (i32.const 42)) 37 | 38 | (assert_invalid 39 | (module (export "a" (func 0))) 40 | "unknown function" 41 | ) 42 | (assert_invalid 43 | (module (func) (export "a" (func 1))) 44 | "unknown function" 45 | ) 46 | (assert_invalid 47 | (module (import "spectest" "print_i32" (func (param i32))) (export "a" (func 1))) 48 | "unknown function" 49 | ) 50 | (assert_invalid 51 | (module (func) (export "a" (func 0)) (export "a" (func 0))) 52 | "duplicate export name" 53 | ) 54 | (assert_invalid 55 | (module (func) (func) (export "a" (func 0)) (export "a" (func 1))) 56 | "duplicate export name" 57 | ) 58 | (assert_invalid 59 | (module (func) (global i32 (i32.const 0)) (export "a" (func 0)) (export "a" (global 0))) 60 | "duplicate export name" 61 | ) 62 | (assert_invalid 63 | (module (func) (table 0 funcref) (export "a" (func 0)) (export "a" (table 0))) 64 | "duplicate export name" 65 | ) 66 | (assert_invalid 67 | (module (func) (memory 0) (export "a" (func 0)) (export "a" (memory 0))) 68 | "duplicate export name" 69 | ) 70 | 71 | 72 | ;; Globals 73 | 74 | (module (global i32 (i32.const 0)) (export "a" (global 0))) 75 | (module (global i32 (i32.const 0)) (export "a" (global 0)) (export "b" (global 0))) 76 | (module (global i32 (i32.const 0)) (global i32 (i32.const 0)) (export "a" (global 0)) (export "b" (global 1))) 77 | 78 | (module (global (export "a") i32 (i32.const 0))) 79 | (module (global i32 (i32.const 0)) (export "a" (global 0))) 80 | (module (global $a (export "a") i32 (i32.const 0))) 81 | (module (global $a i32 (i32.const 0)) (export "a" (global $a))) 82 | (module (export "a" (global 0)) (global i32 (i32.const 0))) 83 | (module (export "a" (global $a)) (global $a i32 (i32.const 0))) 84 | 85 | (module $Global 86 | (export "e" (global $g)) 87 | (global $g i32 (i32.const 42)) 88 | ) 89 | (assert_return (get "e") (i32.const 42)) 90 | (assert_return (get $Global "e") (i32.const 42)) 91 | (module) 92 | (module $Other2) 93 | (assert_return (get $Global "e") (i32.const 42)) 94 | 95 | (assert_invalid 96 | (module (export "a" (global 0))) 97 | "unknown global" 98 | ) 99 | (assert_invalid 100 | (module (global i32 (i32.const 0)) (export "a" (global 1))) 101 | "unknown global" 102 | ) 103 | (assert_invalid 104 | (module (import "spectest" "global_i32" (global i32)) (export "a" (global 1))) 105 | "unknown global" 106 | ) 107 | (assert_invalid 108 | (module (global i32 (i32.const 0)) (export "a" (global 0)) (export "a" (global 0))) 109 | "duplicate export name" 110 | ) 111 | (assert_invalid 112 | (module (global i32 (i32.const 0)) (global i32 (i32.const 0)) (export "a" (global 0)) (export "a" (global 1))) 113 | "duplicate export name" 114 | ) 115 | (assert_invalid 116 | (module (global i32 (i32.const 0)) (func) (export "a" (global 0)) (export "a" (func 0))) 117 | "duplicate export name" 118 | ) 119 | (assert_invalid 120 | (module (global i32 (i32.const 0)) (table 0 funcref) (export "a" (global 0)) (export "a" (table 0))) 121 | "duplicate export name" 122 | ) 123 | (assert_invalid 124 | (module (global i32 (i32.const 0)) (memory 0) (export "a" (global 0)) (export "a" (memory 0))) 125 | "duplicate export name" 126 | ) 127 | 128 | 129 | ;; Tables 130 | 131 | (module (table 0 funcref) (export "a" (table 0))) 132 | (module (table 0 funcref) (export "a" (table 0)) (export "b" (table 0))) 133 | (module (table 0 funcref) (table 0 funcref) (export "a" (table 0)) (export "b" (table 1))) 134 | 135 | (module (table (export "a") 0 funcref)) 136 | (module (table (export "a") 0 1 funcref)) 137 | (module (table 0 funcref) (export "a" (table 0))) 138 | (module (table 0 1 funcref) (export "a" (table 0))) 139 | (module (table $a (export "a") 0 funcref)) 140 | (module (table $a (export "a") 0 1 funcref)) 141 | (module (table $a 0 funcref) (export "a" (table $a))) 142 | (module (table $a 0 1 funcref) (export "a" (table $a))) 143 | (module (export "a" (table 0)) (table 0 funcref)) 144 | (module (export "a" (table 0)) (table 0 1 funcref)) 145 | (module (export "a" (table $a)) (table $a 0 funcref)) 146 | (module (export "a" (table $a)) (table $a 0 1 funcref)) 147 | 148 | (; TODO: access table ;) 149 | 150 | (assert_invalid 151 | (module (export "a" (table 0))) 152 | "unknown table" 153 | ) 154 | (assert_invalid 155 | (module (table 0 funcref) (export "a" (table 1))) 156 | "unknown table" 157 | ) 158 | (assert_invalid 159 | (module (import "spectest" "table" (table 10 20 funcref)) (export "a" (table 1))) 160 | "unknown table" 161 | ) 162 | (assert_invalid 163 | (module (table 0 funcref) (export "a" (table 0)) (export "a" (table 0))) 164 | "duplicate export name" 165 | ) 166 | (assert_invalid 167 | (module (table 0 funcref) (table 0 funcref) (export "a" (table 0)) (export "a" (table 1))) 168 | "duplicate export name" 169 | ) 170 | (assert_invalid 171 | (module (table 0 funcref) (func) (export "a" (table 0)) (export "a" (func 0))) 172 | "duplicate export name" 173 | ) 174 | (assert_invalid 175 | (module (table 0 funcref) (global i32 (i32.const 0)) (export "a" (table 0)) (export "a" (global 0))) 176 | "duplicate export name" 177 | ) 178 | (assert_invalid 179 | (module (table 0 funcref) (memory 0) (export "a" (table 0)) (export "a" (memory 0))) 180 | "duplicate export name" 181 | ) 182 | 183 | 184 | ;; Memories 185 | 186 | (module (memory 0) (export "a" (memory 0))) 187 | (module (memory 0) (export "a" (memory 0)) (export "b" (memory 0))) 188 | ;; No multiple memories yet. 189 | ;; (module (memory 0) (memory 0) (export "a" (memory 0)) (export "b" (memory 1))) 190 | 191 | (module (memory (export "a") 0)) 192 | (module (memory (export "a") 0 1)) 193 | (module (memory 0) (export "a" (memory 0))) 194 | (module (memory 0 1) (export "a" (memory 0))) 195 | (module (memory $a (export "a") 0)) 196 | (module (memory $a (export "a") 0 1)) 197 | (module (memory $a 0) (export "a" (memory $a))) 198 | (module (memory $a 0 1) (export "a" (memory $a))) 199 | (module (export "a" (memory 0)) (memory 0)) 200 | (module (export "a" (memory 0)) (memory 0 1)) 201 | (module (export "a" (memory $a)) (memory $a 0)) 202 | (module (export "a" (memory $a)) (memory $a 0 1)) 203 | 204 | (; TODO: access memory ;) 205 | 206 | (assert_invalid 207 | (module (export "a" (memory 0))) 208 | "unknown memory" 209 | ) 210 | (assert_invalid 211 | (module (memory 0) (export "a" (memory 1))) 212 | "unknown memory" 213 | ) 214 | (assert_invalid 215 | (module (import "spectest" "memory" (memory 1 2)) (export "a" (memory 1))) 216 | "unknown memory" 217 | ) 218 | (assert_invalid 219 | (module (memory 0) (export "a" (memory 0)) (export "a" (memory 0))) 220 | "duplicate export name" 221 | ) 222 | ;; No multiple memories yet. 223 | ;; (assert_invalid 224 | ;; (module (memory 0) (memory 0) (export "a" (memory 0)) (export "a" (memory 1))) 225 | ;; "duplicate export name" 226 | ;; ) 227 | (assert_invalid 228 | (module (memory 0) (func) (export "a" (memory 0)) (export "a" (func 0))) 229 | "duplicate export name" 230 | ) 231 | (assert_invalid 232 | (module (memory 0) (global i32 (i32.const 0)) (export "a" (memory 0)) (export "a" (global 0))) 233 | "duplicate export name" 234 | ) 235 | (assert_invalid 236 | (module (memory 0) (table 0 funcref) (export "a" (memory 0)) (export "a" (table 0))) 237 | "duplicate export name" 238 | ) 239 | -------------------------------------------------------------------------------- /test/core/fac.wast: -------------------------------------------------------------------------------- 1 | (module 2 | ;; Recursive factorial 3 | (func (export "fac-rec") (param i64) (result i64) 4 | (if (result i64) (i64.eq (local.get 0) (i64.const 0)) 5 | (then (i64.const 1)) 6 | (else 7 | (i64.mul (local.get 0) (call 0 (i64.sub (local.get 0) (i64.const 1)))) 8 | ) 9 | ) 10 | ) 11 | 12 | ;; Recursive factorial named 13 | (func $fac-rec-named (export "fac-rec-named") (param $n i64) (result i64) 14 | (if (result i64) (i64.eq (local.get $n) (i64.const 0)) 15 | (then (i64.const 1)) 16 | (else 17 | (i64.mul 18 | (local.get $n) 19 | (call $fac-rec-named (i64.sub (local.get $n) (i64.const 1))) 20 | ) 21 | ) 22 | ) 23 | ) 24 | 25 | ;; Iterative factorial 26 | (func (export "fac-iter") (param i64) (result i64) 27 | (local i64 i64) 28 | (local.set 1 (local.get 0)) 29 | (local.set 2 (i64.const 1)) 30 | (block 31 | (loop 32 | (if 33 | (i64.eq (local.get 1) (i64.const 0)) 34 | (then (br 2)) 35 | (else 36 | (local.set 2 (i64.mul (local.get 1) (local.get 2))) 37 | (local.set 1 (i64.sub (local.get 1) (i64.const 1))) 38 | ) 39 | ) 40 | (br 0) 41 | ) 42 | ) 43 | (local.get 2) 44 | ) 45 | 46 | ;; Iterative factorial named 47 | (func (export "fac-iter-named") (param $n i64) (result i64) 48 | (local $i i64) 49 | (local $res i64) 50 | (local.set $i (local.get $n)) 51 | (local.set $res (i64.const 1)) 52 | (block $done 53 | (loop $loop 54 | (if 55 | (i64.eq (local.get $i) (i64.const 0)) 56 | (then (br $done)) 57 | (else 58 | (local.set $res (i64.mul (local.get $i) (local.get $res))) 59 | (local.set $i (i64.sub (local.get $i) (i64.const 1))) 60 | ) 61 | ) 62 | (br $loop) 63 | ) 64 | ) 65 | (local.get $res) 66 | ) 67 | 68 | ;; Optimized factorial. 69 | (func (export "fac-opt") (param i64) (result i64) 70 | (local i64) 71 | (local.set 1 (i64.const 1)) 72 | (block 73 | (br_if 0 (i64.lt_s (local.get 0) (i64.const 2))) 74 | (loop 75 | (local.set 1 (i64.mul (local.get 1) (local.get 0))) 76 | (local.set 0 (i64.add (local.get 0) (i64.const -1))) 77 | (br_if 0 (i64.gt_s (local.get 0) (i64.const 1))) 78 | ) 79 | ) 80 | (local.get 1) 81 | ) 82 | 83 | ;; Iterative factorial without locals. 84 | (func $pick0 (param i64) (result i64 i64) 85 | (local.get 0) (local.get 0) 86 | ) 87 | (func $pick1 (param i64 i64) (result i64 i64 i64) 88 | (local.get 0) (local.get 1) (local.get 0) 89 | ) 90 | (func (export "fac-ssa") (param i64) (result i64) 91 | (i64.const 1) (local.get 0) 92 | (loop $l (param i64 i64) (result i64) 93 | (call $pick1) (call $pick1) (i64.mul) 94 | (call $pick1) (i64.const 1) (i64.sub) 95 | (call $pick0) (i64.const 0) (i64.gt_u) 96 | (br_if $l) 97 | (drop) (return) 98 | ) 99 | ) 100 | ) 101 | 102 | (assert_return (invoke "fac-rec" (i64.const 25)) (i64.const 7034535277573963776)) 103 | (assert_return (invoke "fac-iter" (i64.const 25)) (i64.const 7034535277573963776)) 104 | (assert_return (invoke "fac-rec-named" (i64.const 25)) (i64.const 7034535277573963776)) 105 | (assert_return (invoke "fac-iter-named" (i64.const 25)) (i64.const 7034535277573963776)) 106 | (assert_return (invoke "fac-opt" (i64.const 25)) (i64.const 7034535277573963776)) 107 | (assert_return (invoke "fac-ssa" (i64.const 25)) (i64.const 7034535277573963776)) 108 | 109 | (assert_exhaustion (invoke "fac-rec" (i64.const 1073741824)) "call stack exhausted") 110 | -------------------------------------------------------------------------------- /test/core/float_memory.wast: -------------------------------------------------------------------------------- 1 | ;; Test that floating-point load and store are bit-preserving. 2 | 3 | ;; Test that load and store do not canonicalize NaNs as x87 does. 4 | 5 | (module 6 | (memory (data "\00\00\a0\7f")) 7 | 8 | (func (export "f32.load") (result f32) (f32.load (i32.const 0))) 9 | (func (export "i32.load") (result i32) (i32.load (i32.const 0))) 10 | (func (export "f32.store") (f32.store (i32.const 0) (f32.const nan:0x200000))) 11 | (func (export "i32.store") (i32.store (i32.const 0) (i32.const 0x7fa00000))) 12 | (func (export "reset") (i32.store (i32.const 0) (i32.const 0))) 13 | ) 14 | 15 | (assert_return (invoke "i32.load") (i32.const 0x7fa00000)) 16 | (assert_return (invoke "f32.load") (f32.const nan:0x200000)) 17 | (invoke "reset") 18 | (assert_return (invoke "i32.load") (i32.const 0x0)) 19 | (assert_return (invoke "f32.load") (f32.const 0.0)) 20 | (invoke "f32.store") 21 | (assert_return (invoke "i32.load") (i32.const 0x7fa00000)) 22 | (assert_return (invoke "f32.load") (f32.const nan:0x200000)) 23 | (invoke "reset") 24 | (assert_return (invoke "i32.load") (i32.const 0x0)) 25 | (assert_return (invoke "f32.load") (f32.const 0.0)) 26 | (invoke "i32.store") 27 | (assert_return (invoke "i32.load") (i32.const 0x7fa00000)) 28 | (assert_return (invoke "f32.load") (f32.const nan:0x200000)) 29 | 30 | (module 31 | (memory (data "\00\00\00\00\00\00\f4\7f")) 32 | 33 | (func (export "f64.load") (result f64) (f64.load (i32.const 0))) 34 | (func (export "i64.load") (result i64) (i64.load (i32.const 0))) 35 | (func (export "f64.store") (f64.store (i32.const 0) (f64.const nan:0x4000000000000))) 36 | (func (export "i64.store") (i64.store (i32.const 0) (i64.const 0x7ff4000000000000))) 37 | (func (export "reset") (i64.store (i32.const 0) (i64.const 0))) 38 | ) 39 | 40 | (assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) 41 | (assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) 42 | (invoke "reset") 43 | (assert_return (invoke "i64.load") (i64.const 0x0)) 44 | (assert_return (invoke "f64.load") (f64.const 0.0)) 45 | (invoke "f64.store") 46 | (assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) 47 | (assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) 48 | (invoke "reset") 49 | (assert_return (invoke "i64.load") (i64.const 0x0)) 50 | (assert_return (invoke "f64.load") (f64.const 0.0)) 51 | (invoke "i64.store") 52 | (assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) 53 | (assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) 54 | 55 | ;; Test that unaligned load and store do not canonicalize NaNs. 56 | 57 | (module 58 | (memory (data "\00\00\00\a0\7f")) 59 | 60 | (func (export "f32.load") (result f32) (f32.load (i32.const 1))) 61 | (func (export "i32.load") (result i32) (i32.load (i32.const 1))) 62 | (func (export "f32.store") (f32.store (i32.const 1) (f32.const nan:0x200000))) 63 | (func (export "i32.store") (i32.store (i32.const 1) (i32.const 0x7fa00000))) 64 | (func (export "reset") (i32.store (i32.const 1) (i32.const 0))) 65 | ) 66 | 67 | (assert_return (invoke "i32.load") (i32.const 0x7fa00000)) 68 | (assert_return (invoke "f32.load") (f32.const nan:0x200000)) 69 | (invoke "reset") 70 | (assert_return (invoke "i32.load") (i32.const 0x0)) 71 | (assert_return (invoke "f32.load") (f32.const 0.0)) 72 | (invoke "f32.store") 73 | (assert_return (invoke "i32.load") (i32.const 0x7fa00000)) 74 | (assert_return (invoke "f32.load") (f32.const nan:0x200000)) 75 | (invoke "reset") 76 | (assert_return (invoke "i32.load") (i32.const 0x0)) 77 | (assert_return (invoke "f32.load") (f32.const 0.0)) 78 | (invoke "i32.store") 79 | (assert_return (invoke "i32.load") (i32.const 0x7fa00000)) 80 | (assert_return (invoke "f32.load") (f32.const nan:0x200000)) 81 | 82 | (module 83 | (memory (data "\00\00\00\00\00\00\00\f4\7f")) 84 | 85 | (func (export "f64.load") (result f64) (f64.load (i32.const 1))) 86 | (func (export "i64.load") (result i64) (i64.load (i32.const 1))) 87 | (func (export "f64.store") (f64.store (i32.const 1) (f64.const nan:0x4000000000000))) 88 | (func (export "i64.store") (i64.store (i32.const 1) (i64.const 0x7ff4000000000000))) 89 | (func (export "reset") (i64.store (i32.const 1) (i64.const 0))) 90 | ) 91 | 92 | (assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) 93 | (assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) 94 | (invoke "reset") 95 | (assert_return (invoke "i64.load") (i64.const 0x0)) 96 | (assert_return (invoke "f64.load") (f64.const 0.0)) 97 | (invoke "f64.store") 98 | (assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) 99 | (assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) 100 | (invoke "reset") 101 | (assert_return (invoke "i64.load") (i64.const 0x0)) 102 | (assert_return (invoke "f64.load") (f64.const 0.0)) 103 | (invoke "i64.store") 104 | (assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) 105 | (assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) 106 | 107 | ;; Test that load and store do not canonicalize NaNs as some JS engines do. 108 | 109 | (module 110 | (memory (data "\01\00\d0\7f")) 111 | 112 | (func (export "f32.load") (result f32) (f32.load (i32.const 0))) 113 | (func (export "i32.load") (result i32) (i32.load (i32.const 0))) 114 | (func (export "f32.store") (f32.store (i32.const 0) (f32.const nan:0x500001))) 115 | (func (export "i32.store") (i32.store (i32.const 0) (i32.const 0x7fd00001))) 116 | (func (export "reset") (i32.store (i32.const 0) (i32.const 0))) 117 | ) 118 | 119 | (assert_return (invoke "i32.load") (i32.const 0x7fd00001)) 120 | (assert_return (invoke "f32.load") (f32.const nan:0x500001)) 121 | (invoke "reset") 122 | (assert_return (invoke "i32.load") (i32.const 0x0)) 123 | (assert_return (invoke "f32.load") (f32.const 0.0)) 124 | (invoke "f32.store") 125 | (assert_return (invoke "i32.load") (i32.const 0x7fd00001)) 126 | (assert_return (invoke "f32.load") (f32.const nan:0x500001)) 127 | (invoke "reset") 128 | (assert_return (invoke "i32.load") (i32.const 0x0)) 129 | (assert_return (invoke "f32.load") (f32.const 0.0)) 130 | (invoke "i32.store") 131 | (assert_return (invoke "i32.load") (i32.const 0x7fd00001)) 132 | (assert_return (invoke "f32.load") (f32.const nan:0x500001)) 133 | 134 | (module 135 | (memory (data "\01\00\00\00\00\00\fc\7f")) 136 | 137 | (func (export "f64.load") (result f64) (f64.load (i32.const 0))) 138 | (func (export "i64.load") (result i64) (i64.load (i32.const 0))) 139 | (func (export "f64.store") (f64.store (i32.const 0) (f64.const nan:0xc000000000001))) 140 | (func (export "i64.store") (i64.store (i32.const 0) (i64.const 0x7ffc000000000001))) 141 | (func (export "reset") (i64.store (i32.const 0) (i64.const 0))) 142 | ) 143 | 144 | (assert_return (invoke "i64.load") (i64.const 0x7ffc000000000001)) 145 | (assert_return (invoke "f64.load") (f64.const nan:0xc000000000001)) 146 | (invoke "reset") 147 | (assert_return (invoke "i64.load") (i64.const 0x0)) 148 | (assert_return (invoke "f64.load") (f64.const 0.0)) 149 | (invoke "f64.store") 150 | (assert_return (invoke "i64.load") (i64.const 0x7ffc000000000001)) 151 | (assert_return (invoke "f64.load") (f64.const nan:0xc000000000001)) 152 | (invoke "reset") 153 | (assert_return (invoke "i64.load") (i64.const 0x0)) 154 | (assert_return (invoke "f64.load") (f64.const 0.0)) 155 | (invoke "i64.store") 156 | (assert_return (invoke "i64.load") (i64.const 0x7ffc000000000001)) 157 | (assert_return (invoke "f64.load") (f64.const nan:0xc000000000001)) 158 | -------------------------------------------------------------------------------- /test/core/forward.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func $even (export "even") (param $n i32) (result i32) 3 | (if (result i32) (i32.eq (local.get $n) (i32.const 0)) 4 | (then (i32.const 1)) 5 | (else (call $odd (i32.sub (local.get $n) (i32.const 1)))) 6 | ) 7 | ) 8 | 9 | (func $odd (export "odd") (param $n i32) (result i32) 10 | (if (result i32) (i32.eq (local.get $n) (i32.const 0)) 11 | (then (i32.const 0)) 12 | (else (call $even (i32.sub (local.get $n) (i32.const 1)))) 13 | ) 14 | ) 15 | ) 16 | 17 | (assert_return (invoke "even" (i32.const 13)) (i32.const 0)) 18 | (assert_return (invoke "even" (i32.const 20)) (i32.const 1)) 19 | (assert_return (invoke "odd" (i32.const 13)) (i32.const 1)) 20 | (assert_return (invoke "odd" (i32.const 20)) (i32.const 0)) 21 | -------------------------------------------------------------------------------- /test/core/func_ptrs.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (type (func)) ;; 0: void -> void 3 | (type $S (func)) ;; 1: void -> void 4 | (type (func (param))) ;; 2: void -> void 5 | (type (func (result i32))) ;; 3: void -> i32 6 | (type (func (param) (result i32))) ;; 4: void -> i32 7 | (type $T (func (param i32) (result i32))) ;; 5: i32 -> i32 8 | (type $U (func (param i32))) ;; 6: i32 -> void 9 | 10 | (func $print (import "spectest" "print_i32") (type 6)) 11 | 12 | (func (type 0)) 13 | (func (type $S)) 14 | 15 | (func (export "one") (type 4) (i32.const 13)) 16 | (func (export "two") (type $T) (i32.add (local.get 0) (i32.const 1))) 17 | 18 | ;; Both signature and parameters are allowed (and required to match) 19 | ;; since this allows the naming of parameters. 20 | (func (export "three") (type $T) (param $a i32) (result i32) 21 | (i32.sub (local.get 0) (i32.const 2)) 22 | ) 23 | 24 | (func (export "four") (type $U) (call $print (local.get 0))) 25 | ) 26 | 27 | (assert_return (invoke "one") (i32.const 13)) 28 | (assert_return (invoke "two" (i32.const 13)) (i32.const 14)) 29 | (assert_return (invoke "three" (i32.const 13)) (i32.const 11)) 30 | (invoke "four" (i32.const 83)) 31 | 32 | (assert_invalid (module (elem (i32.const 0))) "unknown table") 33 | (assert_invalid (module (elem (i32.const 0) 0) (func)) "unknown table") 34 | 35 | (assert_invalid 36 | (module (table 1 funcref) (elem (i64.const 0))) 37 | "type mismatch" 38 | ) 39 | (assert_invalid 40 | (module (table 1 funcref) (elem (i32.ctz (i32.const 0)))) 41 | "constant expression required" 42 | ) 43 | (assert_invalid 44 | (module (table 1 funcref) (elem (nop))) 45 | "constant expression required" 46 | ) 47 | 48 | (assert_invalid (module (func (type 42))) "unknown type") 49 | (assert_invalid (module (import "spectest" "print_i32" (func (type 43)))) "unknown type") 50 | 51 | (module 52 | (type $T (func (param) (result i32))) 53 | (type $U (func (param) (result i32))) 54 | (table funcref (elem $t1 $t2 $t3 $u1 $u2 $t1 $t3)) 55 | 56 | (func $t1 (type $T) (i32.const 1)) 57 | (func $t2 (type $T) (i32.const 2)) 58 | (func $t3 (type $T) (i32.const 3)) 59 | (func $u1 (type $U) (i32.const 4)) 60 | (func $u2 (type $U) (i32.const 5)) 61 | 62 | (func (export "callt") (param $i i32) (result i32) 63 | (call_indirect (type $T) (local.get $i)) 64 | ) 65 | 66 | (func (export "callu") (param $i i32) (result i32) 67 | (call_indirect (type $U) (local.get $i)) 68 | ) 69 | ) 70 | 71 | (assert_return (invoke "callt" (i32.const 0)) (i32.const 1)) 72 | (assert_return (invoke "callt" (i32.const 1)) (i32.const 2)) 73 | (assert_return (invoke "callt" (i32.const 2)) (i32.const 3)) 74 | (assert_return (invoke "callt" (i32.const 3)) (i32.const 4)) 75 | (assert_return (invoke "callt" (i32.const 4)) (i32.const 5)) 76 | (assert_return (invoke "callt" (i32.const 5)) (i32.const 1)) 77 | (assert_return (invoke "callt" (i32.const 6)) (i32.const 3)) 78 | (assert_trap (invoke "callt" (i32.const 7)) "undefined element") 79 | (assert_trap (invoke "callt" (i32.const 100)) "undefined element") 80 | (assert_trap (invoke "callt" (i32.const -1)) "undefined element") 81 | 82 | (assert_return (invoke "callu" (i32.const 0)) (i32.const 1)) 83 | (assert_return (invoke "callu" (i32.const 1)) (i32.const 2)) 84 | (assert_return (invoke "callu" (i32.const 2)) (i32.const 3)) 85 | (assert_return (invoke "callu" (i32.const 3)) (i32.const 4)) 86 | (assert_return (invoke "callu" (i32.const 4)) (i32.const 5)) 87 | (assert_return (invoke "callu" (i32.const 5)) (i32.const 1)) 88 | (assert_return (invoke "callu" (i32.const 6)) (i32.const 3)) 89 | (assert_trap (invoke "callu" (i32.const 7)) "undefined element") 90 | (assert_trap (invoke "callu" (i32.const 100)) "undefined element") 91 | (assert_trap (invoke "callu" (i32.const -1)) "undefined element") 92 | 93 | (module 94 | (type $T (func (result i32))) 95 | (table funcref (elem 0 1)) 96 | 97 | (func $t1 (type $T) (i32.const 1)) 98 | (func $t2 (type $T) (i32.const 2)) 99 | 100 | (func (export "callt") (param $i i32) (result i32) 101 | (call_indirect (type $T) (local.get $i)) 102 | ) 103 | ) 104 | 105 | (assert_return (invoke "callt" (i32.const 0)) (i32.const 1)) 106 | (assert_return (invoke "callt" (i32.const 1)) (i32.const 2)) 107 | -------------------------------------------------------------------------------- /test/core/inline-module.wast: -------------------------------------------------------------------------------- 1 | (func) (memory 0) (func (export "f")) 2 | -------------------------------------------------------------------------------- /test/core/int_literals.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func (export "i32.test") (result i32) (return (i32.const 0x0bAdD00D))) 3 | (func (export "i32.umax") (result i32) (return (i32.const 0xffffffff))) 4 | (func (export "i32.smax") (result i32) (return (i32.const 0x7fffffff))) 5 | (func (export "i32.neg_smax") (result i32) (return (i32.const -0x7fffffff))) 6 | (func (export "i32.smin") (result i32) (return (i32.const -0x80000000))) 7 | (func (export "i32.alt_smin") (result i32) (return (i32.const 0x80000000))) 8 | (func (export "i32.inc_smin") (result i32) (return (i32.add (i32.const -0x80000000) (i32.const 1)))) 9 | (func (export "i32.neg_zero") (result i32) (return (i32.const -0x0))) 10 | (func (export "i32.not_octal") (result i32) (return (i32.const 010))) 11 | (func (export "i32.unsigned_decimal") (result i32) (return (i32.const 4294967295))) 12 | (func (export "i32.plus_sign") (result i32) (return (i32.const +42))) 13 | 14 | (func (export "i64.test") (result i64) (return (i64.const 0x0CABBA6E0ba66a6e))) 15 | (func (export "i64.umax") (result i64) (return (i64.const 0xffffffffffffffff))) 16 | (func (export "i64.smax") (result i64) (return (i64.const 0x7fffffffffffffff))) 17 | (func (export "i64.neg_smax") (result i64) (return (i64.const -0x7fffffffffffffff))) 18 | (func (export "i64.smin") (result i64) (return (i64.const -0x8000000000000000))) 19 | (func (export "i64.alt_smin") (result i64) (return (i64.const 0x8000000000000000))) 20 | (func (export "i64.inc_smin") (result i64) (return (i64.add (i64.const -0x8000000000000000) (i64.const 1)))) 21 | (func (export "i64.neg_zero") (result i64) (return (i64.const -0x0))) 22 | (func (export "i64.not_octal") (result i64) (return (i64.const 010))) 23 | (func (export "i64.unsigned_decimal") (result i64) (return (i64.const 18446744073709551615))) 24 | (func (export "i64.plus_sign") (result i64) (return (i64.const +42))) 25 | 26 | (func (export "i32-dec-sep1") (result i32) (i32.const 1_000_000)) 27 | (func (export "i32-dec-sep2") (result i32) (i32.const 1_0_0_0)) 28 | (func (export "i32-hex-sep1") (result i32) (i32.const 0xa_0f_00_99)) 29 | (func (export "i32-hex-sep2") (result i32) (i32.const 0x1_a_A_0_f)) 30 | 31 | (func (export "i64-dec-sep1") (result i64) (i64.const 1_000_000)) 32 | (func (export "i64-dec-sep2") (result i64) (i64.const 1_0_0_0)) 33 | (func (export "i64-hex-sep1") (result i64) (i64.const 0xa_f00f_0000_9999)) 34 | (func (export "i64-hex-sep2") (result i64) (i64.const 0x1_a_A_0_f)) 35 | ) 36 | 37 | (assert_return (invoke "i32.test") (i32.const 195940365)) 38 | (assert_return (invoke "i32.umax") (i32.const -1)) 39 | (assert_return (invoke "i32.smax") (i32.const 2147483647)) 40 | (assert_return (invoke "i32.neg_smax") (i32.const -2147483647)) 41 | (assert_return (invoke "i32.smin") (i32.const -2147483648)) 42 | (assert_return (invoke "i32.alt_smin") (i32.const -2147483648)) 43 | (assert_return (invoke "i32.inc_smin") (i32.const -2147483647)) 44 | (assert_return (invoke "i32.neg_zero") (i32.const 0)) 45 | (assert_return (invoke "i32.not_octal") (i32.const 10)) 46 | (assert_return (invoke "i32.unsigned_decimal") (i32.const -1)) 47 | (assert_return (invoke "i32.plus_sign") (i32.const 42)) 48 | 49 | (assert_return (invoke "i64.test") (i64.const 913028331277281902)) 50 | (assert_return (invoke "i64.umax") (i64.const -1)) 51 | (assert_return (invoke "i64.smax") (i64.const 9223372036854775807)) 52 | (assert_return (invoke "i64.neg_smax") (i64.const -9223372036854775807)) 53 | (assert_return (invoke "i64.smin") (i64.const -9223372036854775808)) 54 | (assert_return (invoke "i64.alt_smin") (i64.const -9223372036854775808)) 55 | (assert_return (invoke "i64.inc_smin") (i64.const -9223372036854775807)) 56 | (assert_return (invoke "i64.neg_zero") (i64.const 0)) 57 | (assert_return (invoke "i64.not_octal") (i64.const 10)) 58 | (assert_return (invoke "i64.unsigned_decimal") (i64.const -1)) 59 | (assert_return (invoke "i64.plus_sign") (i64.const 42)) 60 | 61 | (assert_return (invoke "i32-dec-sep1") (i32.const 1000000)) 62 | (assert_return (invoke "i32-dec-sep2") (i32.const 1000)) 63 | (assert_return (invoke "i32-hex-sep1") (i32.const 0xa0f0099)) 64 | (assert_return (invoke "i32-hex-sep2") (i32.const 0x1aa0f)) 65 | 66 | (assert_return (invoke "i64-dec-sep1") (i64.const 1000000)) 67 | (assert_return (invoke "i64-dec-sep2") (i64.const 1000)) 68 | (assert_return (invoke "i64-hex-sep1") (i64.const 0xaf00f00009999)) 69 | (assert_return (invoke "i64-hex-sep2") (i64.const 0x1aa0f)) 70 | 71 | (assert_malformed 72 | (module quote "(global i32 (i32.const _100))") 73 | "unknown operator" 74 | ) 75 | (assert_malformed 76 | (module quote "(global i32 (i32.const +_100))") 77 | "unknown operator" 78 | ) 79 | (assert_malformed 80 | (module quote "(global i32 (i32.const -_100))") 81 | "unknown operator" 82 | ) 83 | (assert_malformed 84 | (module quote "(global i32 (i32.const 99_))") 85 | "unknown operator" 86 | ) 87 | (assert_malformed 88 | (module quote "(global i32 (i32.const 1__000))") 89 | "unknown operator" 90 | ) 91 | (assert_malformed 92 | (module quote "(global i32 (i32.const _0x100))") 93 | "unknown operator" 94 | ) 95 | (assert_malformed 96 | (module quote "(global i32 (i32.const 0_x100))") 97 | "unknown operator" 98 | ) 99 | (assert_malformed 100 | (module quote "(global i32 (i32.const 0x_100))") 101 | "unknown operator" 102 | ) 103 | (assert_malformed 104 | (module quote "(global i32 (i32.const 0x00_))") 105 | "unknown operator" 106 | ) 107 | (assert_malformed 108 | (module quote "(global i32 (i32.const 0xff__ffff))") 109 | "unknown operator" 110 | ) 111 | 112 | (assert_malformed 113 | (module quote "(global i64 (i64.const _100))") 114 | "unknown operator" 115 | ) 116 | (assert_malformed 117 | (module quote "(global i64 (i64.const +_100))") 118 | "unknown operator" 119 | ) 120 | (assert_malformed 121 | (module quote "(global i64 (i64.const -_100))") 122 | "unknown operator" 123 | ) 124 | (assert_malformed 125 | (module quote "(global i64 (i64.const 99_))") 126 | "unknown operator" 127 | ) 128 | (assert_malformed 129 | (module quote "(global i64 (i64.const 1__000))") 130 | "unknown operator" 131 | ) 132 | (assert_malformed 133 | (module quote "(global i64 (i64.const _0x100))") 134 | "unknown operator" 135 | ) 136 | (assert_malformed 137 | (module quote "(global i64 (i64.const 0_x100))") 138 | "unknown operator" 139 | ) 140 | (assert_malformed 141 | (module quote "(global i64 (i64.const 0x_100))") 142 | "unknown operator" 143 | ) 144 | (assert_malformed 145 | (module quote "(global i64 (i64.const 0x00_))") 146 | "unknown operator" 147 | ) 148 | (assert_malformed 149 | (module quote "(global i64 (i64.const 0xff__ffff))") 150 | "unknown operator" 151 | ) 152 | -------------------------------------------------------------------------------- /test/core/local_get.wast: -------------------------------------------------------------------------------- 1 | ;; Test `local.get` operator 2 | 3 | (module 4 | ;; Typing 5 | 6 | (func (export "type-local-i32") (result i32) (local i32) (local.get 0)) 7 | (func (export "type-local-i64") (result i64) (local i64) (local.get 0)) 8 | (func (export "type-local-f32") (result f32) (local f32) (local.get 0)) 9 | (func (export "type-local-f64") (result f64) (local f64) (local.get 0)) 10 | 11 | (func (export "type-param-i32") (param i32) (result i32) (local.get 0)) 12 | (func (export "type-param-i64") (param i64) (result i64) (local.get 0)) 13 | (func (export "type-param-f32") (param f32) (result f32) (local.get 0)) 14 | (func (export "type-param-f64") (param f64) (result f64) (local.get 0)) 15 | 16 | (func (export "type-mixed") (param i64 f32 f64 i32 i32) 17 | (local f32 i64 i64 f64) 18 | (drop (i64.eqz (local.get 0))) 19 | (drop (f32.neg (local.get 1))) 20 | (drop (f64.neg (local.get 2))) 21 | (drop (i32.eqz (local.get 3))) 22 | (drop (i32.eqz (local.get 4))) 23 | (drop (f32.neg (local.get 5))) 24 | (drop (i64.eqz (local.get 6))) 25 | (drop (i64.eqz (local.get 7))) 26 | (drop (f64.neg (local.get 8))) 27 | ) 28 | 29 | ;; Reading 30 | 31 | (func (export "read") (param i64 f32 f64 i32 i32) (result f64) 32 | (local f32 i64 i64 f64) 33 | (local.set 5 (f32.const 5.5)) 34 | (local.set 6 (i64.const 6)) 35 | (local.set 8 (f64.const 8)) 36 | (f64.add 37 | (f64.convert_i64_u (local.get 0)) 38 | (f64.add 39 | (f64.promote_f32 (local.get 1)) 40 | (f64.add 41 | (local.get 2) 42 | (f64.add 43 | (f64.convert_i32_u (local.get 3)) 44 | (f64.add 45 | (f64.convert_i32_s (local.get 4)) 46 | (f64.add 47 | (f64.promote_f32 (local.get 5)) 48 | (f64.add 49 | (f64.convert_i64_u (local.get 6)) 50 | (f64.add 51 | (f64.convert_i64_u (local.get 7)) 52 | (local.get 8) 53 | ) 54 | ) 55 | ) 56 | ) 57 | ) 58 | ) 59 | ) 60 | ) 61 | ) 62 | 63 | ;; As parameter of control constructs and instructions 64 | 65 | (func (export "as-block-value") (param i32) (result i32) 66 | (block (result i32) (local.get 0)) 67 | ) 68 | (func (export "as-loop-value") (param i32) (result i32) 69 | (loop (result i32) (local.get 0)) 70 | ) 71 | (func (export "as-br-value") (param i32) (result i32) 72 | (block (result i32) (br 0 (local.get 0))) 73 | ) 74 | (func (export "as-br_if-value") (param i32) (result i32) 75 | (block $l0 (result i32) (br_if $l0 (local.get 0) (i32.const 1))) 76 | ) 77 | 78 | (func (export "as-br_if-value-cond") (param i32) (result i32) 79 | (block (result i32) 80 | (br_if 0 (local.get 0) (local.get 0)) 81 | ) 82 | ) 83 | (func (export "as-br_table-value") (param i32) (result i32) 84 | (block 85 | (block 86 | (block 87 | (br_table 0 1 2 (local.get 0)) 88 | (return (i32.const 0)) 89 | ) 90 | (return (i32.const 1)) 91 | ) 92 | (return (i32.const 2)) 93 | ) 94 | (i32.const 3) 95 | ) 96 | 97 | (func (export "as-return-value") (param i32) (result i32) 98 | (return (local.get 0)) 99 | ) 100 | 101 | (func (export "as-if-then") (param i32) (result i32) 102 | (if (result i32) (local.get 0) (then (local.get 0)) (else (i32.const 0))) 103 | ) 104 | (func (export "as-if-else") (param i32) (result i32) 105 | (if (result i32) (local.get 0) (then (i32.const 1)) (else (local.get 0))) 106 | ) 107 | ) 108 | 109 | (assert_return (invoke "type-local-i32") (i32.const 0)) 110 | (assert_return (invoke "type-local-i64") (i64.const 0)) 111 | (assert_return (invoke "type-local-f32") (f32.const 0)) 112 | (assert_return (invoke "type-local-f64") (f64.const 0)) 113 | 114 | (assert_return (invoke "type-param-i32" (i32.const 2)) (i32.const 2)) 115 | (assert_return (invoke "type-param-i64" (i64.const 3)) (i64.const 3)) 116 | (assert_return (invoke "type-param-f32" (f32.const 4.4)) (f32.const 4.4)) 117 | (assert_return (invoke "type-param-f64" (f64.const 5.5)) (f64.const 5.5)) 118 | 119 | (assert_return (invoke "as-block-value" (i32.const 6)) (i32.const 6)) 120 | (assert_return (invoke "as-loop-value" (i32.const 7)) (i32.const 7)) 121 | 122 | (assert_return (invoke "as-br-value" (i32.const 8)) (i32.const 8)) 123 | (assert_return (invoke "as-br_if-value" (i32.const 9)) (i32.const 9)) 124 | (assert_return (invoke "as-br_if-value-cond" (i32.const 10)) (i32.const 10)) 125 | (assert_return (invoke "as-br_table-value" (i32.const 1)) (i32.const 2)) 126 | 127 | (assert_return (invoke "as-return-value" (i32.const 0)) (i32.const 0)) 128 | 129 | (assert_return (invoke "as-if-then" (i32.const 1)) (i32.const 1)) 130 | (assert_return (invoke "as-if-else" (i32.const 0)) (i32.const 0)) 131 | 132 | (assert_return 133 | (invoke "type-mixed" 134 | (i64.const 1) (f32.const 2.2) (f64.const 3.3) (i32.const 4) (i32.const 5) 135 | ) 136 | ) 137 | 138 | (assert_return 139 | (invoke "read" 140 | (i64.const 1) (f32.const 2) (f64.const 3.3) (i32.const 4) (i32.const 5) 141 | ) 142 | (f64.const 34.8) 143 | ) 144 | 145 | 146 | ;; Invalid typing of access to locals 147 | 148 | (assert_invalid 149 | (module (func $type-local-num-vs-num (result i64) (local i32) (local.get 0))) 150 | "type mismatch" 151 | ) 152 | (assert_invalid 153 | (module (func $type-local-num-vs-num (result i32) (local f32) (i32.eqz (local.get 0)))) 154 | "type mismatch" 155 | ) 156 | (assert_invalid 157 | (module (func $type-local-num-vs-num (result f64) (local f64 i64) (f64.neg (local.get 1)))) 158 | "type mismatch" 159 | ) 160 | 161 | 162 | ;; Invalid typing of access to parameters 163 | 164 | (assert_invalid 165 | (module (func $type-param-num-vs-num (param i32) (result i64) (local.get 0))) 166 | "type mismatch" 167 | ) 168 | (assert_invalid 169 | (module (func $type-param-num-vs-num (param f32) (result i32) (i32.eqz (local.get 0)))) 170 | "type mismatch" 171 | ) 172 | (assert_invalid 173 | (module (func $type-param-num-vs-num (param f64 i64) (result f64) (f64.neg (local.get 1)))) 174 | "type mismatch" 175 | ) 176 | 177 | 178 | ;; local.set should have retval 179 | 180 | (assert_invalid 181 | (module (func $type-empty-vs-i32 (local i32) (local.get 0))) 182 | "type mismatch" 183 | ) 184 | (assert_invalid 185 | (module (func $type-empty-vs-i64 (local i64) (local.get 0))) 186 | "type mismatch" 187 | ) 188 | (assert_invalid 189 | (module (func $type-empty-vs-f32 (local f32) (local.get 0))) 190 | "type mismatch" 191 | ) 192 | (assert_invalid 193 | (module (func $type-empty-vs-f64 (local f64) (local.get 0))) 194 | "type mismatch" 195 | ) 196 | 197 | 198 | ;; Invalid local index 199 | 200 | (assert_invalid 201 | (module (func $unbound-local (local i32 i64) (local.get 3) drop)) 202 | "unknown local" 203 | ) 204 | (assert_invalid 205 | (module (func $large-local (local i32 i64) (local.get 14324343) drop)) 206 | "unknown local" 207 | ) 208 | 209 | (assert_invalid 210 | (module (func $unbound-param (param i32 i64) (local.get 2) drop)) 211 | "unknown local" 212 | ) 213 | (assert_invalid 214 | (module (func $large-param (param i32 i64) (local.get 714324343) drop)) 215 | "unknown local" 216 | ) 217 | 218 | (assert_invalid 219 | (module (func $unbound-mixed (param i32) (local i32 i64) (local.get 3) drop)) 220 | "unknown local" 221 | ) 222 | (assert_invalid 223 | (module (func $large-mixed (param i64) (local i32 i64) (local.get 214324343) drop)) 224 | "unknown local" 225 | ) 226 | 227 | -------------------------------------------------------------------------------- /test/core/memory_redundancy.wast: -------------------------------------------------------------------------------- 1 | ;; Test that optimizers don't do redundant-load, store-to-load, or dead-store 2 | ;; optimizations when there are interfering stores, even of different types 3 | ;; and to non-identical addresses. 4 | 5 | (module 6 | (memory 1 1) 7 | 8 | (func (export "zero_everything") 9 | (i32.store (i32.const 0) (i32.const 0)) 10 | (i32.store (i32.const 4) (i32.const 0)) 11 | (i32.store (i32.const 8) (i32.const 0)) 12 | (i32.store (i32.const 12) (i32.const 0)) 13 | ) 14 | 15 | (func (export "test_store_to_load") (result i32) 16 | (i32.store (i32.const 8) (i32.const 0)) 17 | (f32.store (i32.const 5) (f32.const -0.0)) 18 | (i32.load (i32.const 8)) 19 | ) 20 | 21 | (func (export "test_redundant_load") (result i32) 22 | (local $t i32) 23 | (local $s i32) 24 | (local.set $t (i32.load (i32.const 8))) 25 | (i32.store (i32.const 5) (i32.const 0x80000000)) 26 | (local.set $s (i32.load (i32.const 8))) 27 | (i32.add (local.get $t) (local.get $s)) 28 | ) 29 | 30 | (func (export "test_dead_store") (result f32) 31 | (local $t f32) 32 | (i32.store (i32.const 8) (i32.const 0x23232323)) 33 | (local.set $t (f32.load (i32.const 11))) 34 | (i32.store (i32.const 8) (i32.const 0)) 35 | (local.get $t) 36 | ) 37 | 38 | ;; A function named "malloc" which implementations nonetheless shouldn't 39 | ;; assume behaves like C malloc. 40 | (func $malloc (export "malloc") 41 | (param $size i32) 42 | (result i32) 43 | (i32.const 16) 44 | ) 45 | 46 | ;; Call malloc twice, but unlike C malloc, we don't get non-aliasing pointers. 47 | (func (export "malloc_aliasing") 48 | (result i32) 49 | (local $x i32) 50 | (local $y i32) 51 | (local.set $x (call $malloc (i32.const 4))) 52 | (local.set $y (call $malloc (i32.const 4))) 53 | (i32.store (local.get $x) (i32.const 42)) 54 | (i32.store (local.get $y) (i32.const 43)) 55 | (i32.load (local.get $x)) 56 | ) 57 | ) 58 | 59 | (assert_return (invoke "test_store_to_load") (i32.const 0x00000080)) 60 | (invoke "zero_everything") 61 | (assert_return (invoke "test_redundant_load") (i32.const 0x00000080)) 62 | (invoke "zero_everything") 63 | (assert_return (invoke "test_dead_store") (f32.const 0x1.18p-144)) 64 | (invoke "zero_everything") 65 | (assert_return (invoke "malloc_aliasing") (i32.const 43)) 66 | -------------------------------------------------------------------------------- /test/core/memory_size.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (memory 0) 3 | (func (export "size") (result i32) (memory.size)) 4 | (func (export "grow") (param $sz i32) (drop (memory.grow (local.get $sz)))) 5 | ) 6 | 7 | (assert_return (invoke "size") (i32.const 0)) 8 | (assert_return (invoke "grow" (i32.const 1))) 9 | (assert_return (invoke "size") (i32.const 1)) 10 | (assert_return (invoke "grow" (i32.const 4))) 11 | (assert_return (invoke "size") (i32.const 5)) 12 | (assert_return (invoke "grow" (i32.const 0))) 13 | (assert_return (invoke "size") (i32.const 5)) 14 | 15 | (module 16 | (memory 1) 17 | (func (export "size") (result i32) (memory.size)) 18 | (func (export "grow") (param $sz i32) (drop (memory.grow (local.get $sz)))) 19 | ) 20 | 21 | (assert_return (invoke "size") (i32.const 1)) 22 | (assert_return (invoke "grow" (i32.const 1))) 23 | (assert_return (invoke "size") (i32.const 2)) 24 | (assert_return (invoke "grow" (i32.const 4))) 25 | (assert_return (invoke "size") (i32.const 6)) 26 | (assert_return (invoke "grow" (i32.const 0))) 27 | (assert_return (invoke "size") (i32.const 6)) 28 | 29 | (module 30 | (memory 0 2) 31 | (func (export "size") (result i32) (memory.size)) 32 | (func (export "grow") (param $sz i32) (drop (memory.grow (local.get $sz)))) 33 | ) 34 | 35 | (assert_return (invoke "size") (i32.const 0)) 36 | (assert_return (invoke "grow" (i32.const 3))) 37 | (assert_return (invoke "size") (i32.const 0)) 38 | (assert_return (invoke "grow" (i32.const 1))) 39 | (assert_return (invoke "size") (i32.const 1)) 40 | (assert_return (invoke "grow" (i32.const 0))) 41 | (assert_return (invoke "size") (i32.const 1)) 42 | (assert_return (invoke "grow" (i32.const 4))) 43 | (assert_return (invoke "size") (i32.const 1)) 44 | (assert_return (invoke "grow" (i32.const 1))) 45 | (assert_return (invoke "size") (i32.const 2)) 46 | 47 | (module 48 | (memory 3 8) 49 | (func (export "size") (result i32) (memory.size)) 50 | (func (export "grow") (param $sz i32) (drop (memory.grow (local.get $sz)))) 51 | ) 52 | 53 | (assert_return (invoke "size") (i32.const 3)) 54 | (assert_return (invoke "grow" (i32.const 1))) 55 | (assert_return (invoke "size") (i32.const 4)) 56 | (assert_return (invoke "grow" (i32.const 3))) 57 | (assert_return (invoke "size") (i32.const 7)) 58 | (assert_return (invoke "grow" (i32.const 0))) 59 | (assert_return (invoke "size") (i32.const 7)) 60 | (assert_return (invoke "grow" (i32.const 2))) 61 | (assert_return (invoke "size") (i32.const 7)) 62 | (assert_return (invoke "grow" (i32.const 1))) 63 | (assert_return (invoke "size") (i32.const 8)) 64 | 65 | 66 | ;; Type errors 67 | 68 | (assert_invalid 69 | (module 70 | (memory 1) 71 | (func $type-result-i32-vs-empty 72 | (memory.size) 73 | ) 74 | ) 75 | "type mismatch" 76 | ) 77 | (assert_invalid 78 | (module 79 | (memory 1) 80 | (func $type-result-i32-vs-f32 (result f32) 81 | (memory.size) 82 | ) 83 | ) 84 | "type mismatch" 85 | ) 86 | -------------------------------------------------------------------------------- /test/core/ref_func.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func (export "f") (param $x i32) (result i32) (local.get $x)) 3 | ) 4 | (register "M") 5 | 6 | (module 7 | (func $f (import "M" "f") (param i32) (result i32)) 8 | (func $g (param $x i32) (result i32) 9 | (i32.add (local.get $x) (i32.const 1)) 10 | ) 11 | 12 | (global funcref (ref.func $f)) 13 | (global funcref (ref.func $g)) 14 | (global $v (mut funcref) (ref.func $f)) 15 | 16 | (global funcref (ref.func $gf1)) 17 | (global funcref (ref.func $gf2)) 18 | (func (drop (ref.func $ff1)) (drop (ref.func $ff2))) 19 | (elem declare func $gf1 $ff1) 20 | (elem declare funcref (ref.func $gf2) (ref.func $ff2)) 21 | (func $gf1) 22 | (func $gf2) 23 | (func $ff1) 24 | (func $ff2) 25 | 26 | (func (export "is_null-f") (result i32) 27 | (ref.is_null (ref.func $f)) 28 | ) 29 | (func (export "is_null-g") (result i32) 30 | (ref.is_null (ref.func $g)) 31 | ) 32 | (func (export "is_null-v") (result i32) 33 | (ref.is_null (global.get $v)) 34 | ) 35 | 36 | (func (export "set-f") (global.set $v (ref.func $f))) 37 | (func (export "set-g") (global.set $v (ref.func $g))) 38 | 39 | (table $t 1 funcref) 40 | (elem declare func $f $g) 41 | 42 | (func (export "call-f") (param $x i32) (result i32) 43 | (table.set $t (i32.const 0) (ref.func $f)) 44 | (call_indirect $t (param i32) (result i32) (local.get $x) (i32.const 0)) 45 | ) 46 | (func (export "call-g") (param $x i32) (result i32) 47 | (table.set $t (i32.const 0) (ref.func $g)) 48 | (call_indirect $t (param i32) (result i32) (local.get $x) (i32.const 0)) 49 | ) 50 | (func (export "call-v") (param $x i32) (result i32) 51 | (table.set $t (i32.const 0) (global.get $v)) 52 | (call_indirect $t (param i32) (result i32) (local.get $x) (i32.const 0)) 53 | ) 54 | ) 55 | 56 | (assert_return (invoke "is_null-f") (i32.const 0)) 57 | (assert_return (invoke "is_null-g") (i32.const 0)) 58 | (assert_return (invoke "is_null-v") (i32.const 0)) 59 | 60 | (assert_return (invoke "call-f" (i32.const 4)) (i32.const 4)) 61 | (assert_return (invoke "call-g" (i32.const 4)) (i32.const 5)) 62 | (assert_return (invoke "call-v" (i32.const 4)) (i32.const 4)) 63 | (invoke "set-g") 64 | (assert_return (invoke "call-v" (i32.const 4)) (i32.const 5)) 65 | (invoke "set-f") 66 | (assert_return (invoke "call-v" (i32.const 4)) (i32.const 4)) 67 | 68 | (assert_invalid 69 | (module 70 | (func $f (import "M" "f") (param i32) (result i32)) 71 | (func $g (import "M" "g") (param i32) (result i32)) 72 | (global funcref (ref.func 7)) 73 | ) 74 | "unknown function 7" 75 | ) 76 | 77 | 78 | ;; Reference declaration 79 | 80 | (module 81 | (func $f1) 82 | (func $f2) 83 | (func $f3) 84 | (func $f4) 85 | (func $f5) 86 | (func $f6) 87 | 88 | (table $t 1 funcref) 89 | 90 | (global funcref (ref.func $f1)) 91 | (export "f" (func $f2)) 92 | (elem (table $t) (i32.const 0) func $f3) 93 | (elem (table $t) (i32.const 0) funcref (ref.func $f4)) 94 | (elem func $f5) 95 | (elem funcref (ref.func $f6)) 96 | 97 | (func 98 | (ref.func $f1) 99 | (ref.func $f2) 100 | (ref.func $f3) 101 | (ref.func $f4) 102 | (ref.func $f5) 103 | (ref.func $f6) 104 | (return) 105 | ) 106 | ) 107 | 108 | (assert_invalid 109 | (module (func $f (drop (ref.func $f)))) 110 | "undeclared function reference" 111 | ) 112 | (assert_invalid 113 | (module (start $f) (func $f (drop (ref.func $f)))) 114 | "undeclared function reference" 115 | ) 116 | -------------------------------------------------------------------------------- /test/core/ref_is_null.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func $f1 (export "funcref") (param $x funcref) (result i32) 3 | (ref.is_null (local.get $x)) 4 | ) 5 | (func $f2 (export "externref") (param $x externref) (result i32) 6 | (ref.is_null (local.get $x)) 7 | ) 8 | 9 | (table $t1 2 funcref) 10 | (table $t2 2 externref) 11 | (elem (table $t1) (i32.const 1) func $dummy) 12 | (func $dummy) 13 | 14 | (func (export "init") (param $r externref) 15 | (table.set $t2 (i32.const 1) (local.get $r)) 16 | ) 17 | (func (export "deinit") 18 | (table.set $t1 (i32.const 1) (ref.null func)) 19 | (table.set $t2 (i32.const 1) (ref.null extern)) 20 | ) 21 | 22 | (func (export "funcref-elem") (param $x i32) (result i32) 23 | (call $f1 (table.get $t1 (local.get $x))) 24 | ) 25 | (func (export "externref-elem") (param $x i32) (result i32) 26 | (call $f2 (table.get $t2 (local.get $x))) 27 | ) 28 | ) 29 | 30 | (assert_return (invoke "funcref" (ref.null func)) (i32.const 1)) 31 | (assert_return (invoke "externref" (ref.null extern)) (i32.const 1)) 32 | 33 | (assert_return (invoke "externref" (ref.extern 1)) (i32.const 0)) 34 | 35 | (invoke "init" (ref.extern 0)) 36 | 37 | (assert_return (invoke "funcref-elem" (i32.const 0)) (i32.const 1)) 38 | (assert_return (invoke "externref-elem" (i32.const 0)) (i32.const 1)) 39 | 40 | (assert_return (invoke "funcref-elem" (i32.const 1)) (i32.const 0)) 41 | (assert_return (invoke "externref-elem" (i32.const 1)) (i32.const 0)) 42 | 43 | (invoke "deinit") 44 | 45 | (assert_return (invoke "funcref-elem" (i32.const 0)) (i32.const 1)) 46 | (assert_return (invoke "externref-elem" (i32.const 0)) (i32.const 1)) 47 | 48 | (assert_return (invoke "funcref-elem" (i32.const 1)) (i32.const 1)) 49 | (assert_return (invoke "externref-elem" (i32.const 1)) (i32.const 1)) 50 | 51 | (assert_invalid 52 | (module (func $ref-vs-num (param i32) (ref.is_null (local.get 0)))) 53 | "type mismatch" 54 | ) 55 | (assert_invalid 56 | (module (func $ref-vs-empty (ref.is_null))) 57 | "type mismatch" 58 | ) 59 | -------------------------------------------------------------------------------- /test/core/ref_null.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func (export "externref") (result externref) (ref.null extern)) 3 | (func (export "funcref") (result funcref) (ref.null func)) 4 | 5 | (global externref (ref.null extern)) 6 | (global funcref (ref.null func)) 7 | ) 8 | 9 | (assert_return (invoke "externref") (ref.null extern)) 10 | (assert_return (invoke "funcref") (ref.null func)) 11 | -------------------------------------------------------------------------------- /test/core/stack.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func (export "fac-expr") (param $n i64) (result i64) 3 | (local $i i64) 4 | (local $res i64) 5 | (local.set $i (local.get $n)) 6 | (local.set $res (i64.const 1)) 7 | (block $done 8 | (loop $loop 9 | (if 10 | (i64.eq (local.get $i) (i64.const 0)) 11 | (then (br $done)) 12 | (else 13 | (local.set $res (i64.mul (local.get $i) (local.get $res))) 14 | (local.set $i (i64.sub (local.get $i) (i64.const 1))) 15 | ) 16 | ) 17 | (br $loop) 18 | ) 19 | ) 20 | (local.get $res) 21 | ) 22 | 23 | (func (export "fac-stack") (param $n i64) (result i64) 24 | (local $i i64) 25 | (local $res i64) 26 | (local.get $n) 27 | (local.set $i) 28 | (i64.const 1) 29 | (local.set $res) 30 | (block $done 31 | (loop $loop 32 | (local.get $i) 33 | (i64.const 0) 34 | (i64.eq) 35 | (if 36 | (then (br $done)) 37 | (else 38 | (local.get $i) 39 | (local.get $res) 40 | (i64.mul) 41 | (local.set $res) 42 | (local.get $i) 43 | (i64.const 1) 44 | (i64.sub) 45 | (local.set $i) 46 | ) 47 | ) 48 | (br $loop) 49 | ) 50 | ) 51 | (local.get $res) 52 | ) 53 | 54 | (func (export "fac-stack-raw") (param $n i64) (result i64) 55 | (local $i i64) 56 | (local $res i64) 57 | local.get $n 58 | local.set $i 59 | i64.const 1 60 | local.set $res 61 | block $done 62 | loop $loop 63 | local.get $i 64 | i64.const 0 65 | i64.eq 66 | if $body 67 | br $done 68 | else $body 69 | local.get $i 70 | local.get $res 71 | i64.mul 72 | local.set $res 73 | local.get $i 74 | i64.const 1 75 | i64.sub 76 | local.set $i 77 | end $body 78 | br $loop 79 | end $loop 80 | end $done 81 | local.get $res 82 | ) 83 | 84 | (func (export "fac-mixed") (param $n i64) (result i64) 85 | (local $i i64) 86 | (local $res i64) 87 | (local.set $i (local.get $n)) 88 | (local.set $res (i64.const 1)) 89 | (block $done 90 | (loop $loop 91 | (i64.eq (local.get $i) (i64.const 0)) 92 | (if 93 | (then (br $done)) 94 | (else 95 | (i64.mul (local.get $i) (local.get $res)) 96 | (local.set $res) 97 | (i64.sub (local.get $i) (i64.const 1)) 98 | (local.set $i) 99 | ) 100 | ) 101 | (br $loop) 102 | ) 103 | ) 104 | (local.get $res) 105 | ) 106 | 107 | (func (export "fac-mixed-raw") (param $n i64) (result i64) 108 | (local $i i64) 109 | (local $res i64) 110 | (local.set $i (local.get $n)) 111 | (local.set $res (i64.const 1)) 112 | block $done 113 | loop $loop 114 | (i64.eq (local.get $i) (i64.const 0)) 115 | if 116 | br $done 117 | else 118 | (i64.mul (local.get $i) (local.get $res)) 119 | local.set $res 120 | (i64.sub (local.get $i) (i64.const 1)) 121 | local.set $i 122 | end 123 | br $loop 124 | end 125 | end 126 | local.get $res 127 | ) 128 | 129 | (global $temp (mut i32) (i32.const 0)) 130 | (func $add_one_to_global (result i32) 131 | (local i32) 132 | (global.set $temp (i32.add (i32.const 1) (global.get $temp))) 133 | (global.get $temp) 134 | ) 135 | (func $add_one_to_global_and_drop 136 | (drop (call $add_one_to_global)) 137 | ) 138 | (func (export "not-quite-a-tree") (result i32) 139 | call $add_one_to_global 140 | call $add_one_to_global 141 | call $add_one_to_global_and_drop 142 | i32.add 143 | ) 144 | ) 145 | 146 | (assert_return (invoke "fac-expr" (i64.const 25)) (i64.const 7034535277573963776)) 147 | (assert_return (invoke "fac-stack" (i64.const 25)) (i64.const 7034535277573963776)) 148 | (assert_return (invoke "fac-mixed" (i64.const 25)) (i64.const 7034535277573963776)) 149 | 150 | (assert_return (invoke "not-quite-a-tree") (i32.const 3)) 151 | (assert_return (invoke "not-quite-a-tree") (i32.const 9)) 152 | 153 | 154 | ;; Syntax of flat call_indirect 155 | 156 | (module 157 | (type $proc (func)) 158 | (table 1 funcref) 159 | 160 | (func 161 | (block i32.const 0 call_indirect) 162 | (loop i32.const 0 call_indirect) 163 | (if (i32.const 0) (then i32.const 0 call_indirect)) 164 | (if (i32.const 0) 165 | (then i32.const 0 call_indirect) 166 | (else i32.const 0 call_indirect) 167 | ) 168 | (block i32.const 0 call_indirect (type $proc)) 169 | (loop i32.const 0 call_indirect (type $proc)) 170 | (if (i32.const 0) (then i32.const 0 call_indirect (type $proc))) 171 | (if (i32.const 0) 172 | (then i32.const 0 call_indirect (type $proc)) 173 | (else i32.const 0 call_indirect (type $proc)) 174 | ) 175 | (block i32.const 0 i32.const 0 call_indirect (param i32)) 176 | (loop i32.const 0 i32.const 0 call_indirect (param i32)) 177 | (if (i32.const 0) (then i32.const 0 i32.const 0 call_indirect (param i32))) 178 | (if (i32.const 0) 179 | (then i32.const 0 i32.const 0 call_indirect (param i32)) 180 | (else i32.const 0 i32.const 0 call_indirect (param i32)) 181 | ) 182 | (block (result i32) i32.const 0 call_indirect (result i32)) (drop) 183 | (loop (result i32) i32.const 0 call_indirect (result i32)) (drop) 184 | (if (result i32) (i32.const 0) 185 | (then i32.const 0 call_indirect (result i32)) 186 | (else i32.const 0 call_indirect (result i32)) 187 | ) (drop) 188 | (block i32.const 0 call_indirect (type $proc) (param) (result)) 189 | (loop i32.const 0 call_indirect (type $proc) (param) (result)) 190 | (if (i32.const 0) 191 | (then i32.const 0 call_indirect (type $proc) (param) (result)) 192 | ) 193 | (if (i32.const 0) 194 | (then i32.const 0 call_indirect (type $proc) (param) (param) (result)) 195 | (else i32.const 0 call_indirect (type $proc) (param) (result) (result)) 196 | ) 197 | 198 | block i32.const 0 call_indirect end 199 | loop i32.const 0 call_indirect end 200 | i32.const 0 if i32.const 0 call_indirect end 201 | i32.const 0 if i32.const 0 call_indirect else i32.const 0 call_indirect end 202 | block i32.const 0 call_indirect (type $proc) end 203 | loop i32.const 0 call_indirect (type $proc) end 204 | i32.const 0 if i32.const 0 call_indirect (type $proc) end 205 | i32.const 0 206 | if 207 | i32.const 0 call_indirect (type $proc) 208 | else 209 | i32.const 0 call_indirect (type $proc) 210 | end 211 | block i32.const 0 i32.const 0 call_indirect (param i32) end 212 | loop i32.const 0 i32.const 0 call_indirect (param i32) end 213 | i32.const 0 if i32.const 0 i32.const 0 call_indirect (param i32) end 214 | i32.const 0 215 | if 216 | i32.const 0 i32.const 0 call_indirect (param i32) 217 | else 218 | i32.const 0 i32.const 0 call_indirect (param i32) 219 | end 220 | block (result i32) i32.const 0 call_indirect (result i32) end drop 221 | loop (result i32) i32.const 0 call_indirect (result i32) end drop 222 | i32.const 0 223 | if (result i32) 224 | i32.const 0 call_indirect (result i32) 225 | else 226 | i32.const 0 call_indirect (result i32) 227 | end drop 228 | block i32.const 0 call_indirect (type $proc) (param) (result) end 229 | loop i32.const 0 call_indirect (type $proc) (param) (result) end 230 | i32.const 0 if i32.const 0 call_indirect (type $proc) (param) (result) end 231 | i32.const 0 232 | if 233 | i32.const 0 call_indirect (type $proc) (param) (result) 234 | else 235 | i32.const 0 call_indirect (type $proc) (param) (param) (result) (result) 236 | end 237 | i32.const 0 call_indirect 238 | ) 239 | ) 240 | -------------------------------------------------------------------------------- /test/core/start.wast: -------------------------------------------------------------------------------- 1 | (assert_invalid 2 | (module (func) (start 1)) 3 | "unknown function" 4 | ) 5 | 6 | (assert_invalid 7 | (module 8 | (func $main (result i32) (return (i32.const 0))) 9 | (start $main) 10 | ) 11 | "start function" 12 | ) 13 | (assert_invalid 14 | (module 15 | (func $main (param $a i32)) 16 | (start $main) 17 | ) 18 | "start function" 19 | ) 20 | 21 | (module 22 | (memory (data "A")) 23 | (func $inc 24 | (i32.store8 25 | (i32.const 0) 26 | (i32.add 27 | (i32.load8_u (i32.const 0)) 28 | (i32.const 1) 29 | ) 30 | ) 31 | ) 32 | (func $get (result i32) 33 | (return (i32.load8_u (i32.const 0))) 34 | ) 35 | (func $main 36 | (call $inc) 37 | (call $inc) 38 | (call $inc) 39 | ) 40 | 41 | (start $main) 42 | (export "inc" (func $inc)) 43 | (export "get" (func $get)) 44 | ) 45 | (assert_return (invoke "get") (i32.const 68)) 46 | (invoke "inc") 47 | (assert_return (invoke "get") (i32.const 69)) 48 | (invoke "inc") 49 | (assert_return (invoke "get") (i32.const 70)) 50 | 51 | (module 52 | (memory (data "A")) 53 | (func $inc 54 | (i32.store8 55 | (i32.const 0) 56 | (i32.add 57 | (i32.load8_u (i32.const 0)) 58 | (i32.const 1) 59 | ) 60 | ) 61 | ) 62 | (func $get (result i32) 63 | (return (i32.load8_u (i32.const 0))) 64 | ) 65 | (func $main 66 | (call $inc) 67 | (call $inc) 68 | (call $inc) 69 | ) 70 | (start 2) 71 | (export "inc" (func $inc)) 72 | (export "get" (func $get)) 73 | ) 74 | (assert_return (invoke "get") (i32.const 68)) 75 | (invoke "inc") 76 | (assert_return (invoke "get") (i32.const 69)) 77 | (invoke "inc") 78 | (assert_return (invoke "get") (i32.const 70)) 79 | 80 | (module 81 | (func $print_i32 (import "spectest" "print_i32") (param i32)) 82 | (func $main (call $print_i32 (i32.const 1))) 83 | (start 1) 84 | ) 85 | 86 | (module 87 | (func $print_i32 (import "spectest" "print_i32") (param i32)) 88 | (func $main (call $print_i32 (i32.const 2))) 89 | (start $main) 90 | ) 91 | 92 | (module 93 | (func $print (import "spectest" "print")) 94 | (start $print) 95 | ) 96 | 97 | (assert_trap 98 | (module (func $main (unreachable)) (start $main)) 99 | "unreachable" 100 | ) 101 | 102 | (assert_malformed 103 | (module quote "(module (func $a (unreachable)) (func $b (unreachable)) (start $a) (start $b))") 104 | "multiple start sections" 105 | ) 106 | -------------------------------------------------------------------------------- /test/core/switch.wast: -------------------------------------------------------------------------------- 1 | (module 2 | ;; Statement switch 3 | (func (export "stmt") (param $i i32) (result i32) 4 | (local $j i32) 5 | (local.set $j (i32.const 100)) 6 | (block $switch 7 | (block $7 8 | (block $default 9 | (block $6 10 | (block $5 11 | (block $4 12 | (block $3 13 | (block $2 14 | (block $1 15 | (block $0 16 | (br_table $0 $1 $2 $3 $4 $5 $6 $7 $default 17 | (local.get $i) 18 | ) 19 | ) ;; 0 20 | (return (local.get $i)) 21 | ) ;; 1 22 | (nop) 23 | ;; fallthrough 24 | ) ;; 2 25 | ;; fallthrough 26 | ) ;; 3 27 | (local.set $j (i32.sub (i32.const 0) (local.get $i))) 28 | (br $switch) 29 | ) ;; 4 30 | (br $switch) 31 | ) ;; 5 32 | (local.set $j (i32.const 101)) 33 | (br $switch) 34 | ) ;; 6 35 | (local.set $j (i32.const 101)) 36 | ;; fallthrough 37 | ) ;; default 38 | (local.set $j (i32.const 102)) 39 | ) ;; 7 40 | ;; fallthrough 41 | ) 42 | (return (local.get $j)) 43 | ) 44 | 45 | ;; Expression switch 46 | (func (export "expr") (param $i i64) (result i64) 47 | (local $j i64) 48 | (local.set $j (i64.const 100)) 49 | (return 50 | (block $switch (result i64) 51 | (block $7 52 | (block $default 53 | (block $4 54 | (block $5 55 | (block $6 56 | (block $3 57 | (block $2 58 | (block $1 59 | (block $0 60 | (br_table $0 $1 $2 $3 $4 $5 $6 $7 $default 61 | (i32.wrap_i64 (local.get $i)) 62 | ) 63 | ) ;; 0 64 | (return (local.get $i)) 65 | ) ;; 1 66 | (nop) 67 | ;; fallthrough 68 | ) ;; 2 69 | ;; fallthrough 70 | ) ;; 3 71 | (br $switch (i64.sub (i64.const 0) (local.get $i))) 72 | ) ;; 6 73 | (local.set $j (i64.const 101)) 74 | ;; fallthrough 75 | ) ;; 4 76 | ;; fallthrough 77 | ) ;; 5 78 | ;; fallthrough 79 | ) ;; default 80 | (br $switch (local.get $j)) 81 | ) ;; 7 82 | (i64.const -5) 83 | ) 84 | ) 85 | ) 86 | 87 | ;; Argument switch 88 | (func (export "arg") (param $i i32) (result i32) 89 | (return 90 | (block $2 (result i32) 91 | (i32.add (i32.const 10) 92 | (block $1 (result i32) 93 | (i32.add (i32.const 100) 94 | (block $0 (result i32) 95 | (i32.add (i32.const 1000) 96 | (block $default (result i32) 97 | (br_table $0 $1 $2 $default 98 | (i32.mul (i32.const 2) (local.get $i)) 99 | (i32.and (i32.const 3) (local.get $i)) 100 | ) 101 | ) 102 | ) 103 | ) 104 | ) 105 | ) 106 | ) 107 | ) 108 | ) 109 | ) 110 | 111 | ;; Corner cases 112 | (func (export "corner") (result i32) 113 | (block 114 | (br_table 0 (i32.const 0)) 115 | ) 116 | (i32.const 1) 117 | ) 118 | ) 119 | 120 | (assert_return (invoke "stmt" (i32.const 0)) (i32.const 0)) 121 | (assert_return (invoke "stmt" (i32.const 1)) (i32.const -1)) 122 | (assert_return (invoke "stmt" (i32.const 2)) (i32.const -2)) 123 | (assert_return (invoke "stmt" (i32.const 3)) (i32.const -3)) 124 | (assert_return (invoke "stmt" (i32.const 4)) (i32.const 100)) 125 | (assert_return (invoke "stmt" (i32.const 5)) (i32.const 101)) 126 | (assert_return (invoke "stmt" (i32.const 6)) (i32.const 102)) 127 | (assert_return (invoke "stmt" (i32.const 7)) (i32.const 100)) 128 | (assert_return (invoke "stmt" (i32.const -10)) (i32.const 102)) 129 | 130 | (assert_return (invoke "expr" (i64.const 0)) (i64.const 0)) 131 | (assert_return (invoke "expr" (i64.const 1)) (i64.const -1)) 132 | (assert_return (invoke "expr" (i64.const 2)) (i64.const -2)) 133 | (assert_return (invoke "expr" (i64.const 3)) (i64.const -3)) 134 | (assert_return (invoke "expr" (i64.const 6)) (i64.const 101)) 135 | (assert_return (invoke "expr" (i64.const 7)) (i64.const -5)) 136 | (assert_return (invoke "expr" (i64.const -10)) (i64.const 100)) 137 | 138 | (assert_return (invoke "arg" (i32.const 0)) (i32.const 110)) 139 | (assert_return (invoke "arg" (i32.const 1)) (i32.const 12)) 140 | (assert_return (invoke "arg" (i32.const 2)) (i32.const 4)) 141 | (assert_return (invoke "arg" (i32.const 3)) (i32.const 1116)) 142 | (assert_return (invoke "arg" (i32.const 4)) (i32.const 118)) 143 | (assert_return (invoke "arg" (i32.const 5)) (i32.const 20)) 144 | (assert_return (invoke "arg" (i32.const 6)) (i32.const 12)) 145 | (assert_return (invoke "arg" (i32.const 7)) (i32.const 1124)) 146 | (assert_return (invoke "arg" (i32.const 8)) (i32.const 126)) 147 | 148 | (assert_return (invoke "corner") (i32.const 1)) 149 | 150 | (assert_invalid (module (func (br_table 3 (i32.const 0)))) "unknown label") 151 | -------------------------------------------------------------------------------- /test/core/table-sub.wast: -------------------------------------------------------------------------------- 1 | (assert_invalid 2 | (module 3 | (table $t1 10 funcref) 4 | (table $t2 10 externref) 5 | (func $f 6 | (table.copy $t1 $t2 (i32.const 0) (i32.const 1) (i32.const 2)) 7 | ) 8 | ) 9 | "type mismatch" 10 | ) 11 | 12 | (assert_invalid 13 | (module 14 | (table $t 10 funcref) 15 | (elem $el externref) 16 | (func $f 17 | (table.init $t $el (i32.const 0) (i32.const 1) (i32.const 2)) 18 | ) 19 | ) 20 | "type mismatch" 21 | ) 22 | -------------------------------------------------------------------------------- /test/core/table.wast: -------------------------------------------------------------------------------- 1 | ;; Test table section structure 2 | 3 | (module (table 0 funcref)) 4 | (module (table 1 funcref)) 5 | (module (table 0 0 funcref)) 6 | (module (table 0 1 funcref)) 7 | (module (table 1 256 funcref)) 8 | (module (table 0 65536 funcref)) 9 | (module (table 0 0xffff_ffff funcref)) 10 | 11 | (module (table 0 funcref) (table 0 funcref)) 12 | (module (table (import "spectest" "table") 0 funcref) (table 0 funcref)) 13 | 14 | (assert_invalid (module (elem (i32.const 0))) "unknown table") 15 | (assert_invalid (module (elem (i32.const 0) $f) (func $f)) "unknown table") 16 | 17 | 18 | (assert_invalid 19 | (module (table 1 0 funcref)) 20 | "size minimum must not be greater than maximum" 21 | ) 22 | (assert_invalid 23 | (module (table 0xffff_ffff 0 funcref)) 24 | "size minimum must not be greater than maximum" 25 | ) 26 | 27 | (assert_malformed 28 | (module quote "(table 0x1_0000_0000 funcref)") 29 | "i32 constant out of range" 30 | ) 31 | (assert_malformed 32 | (module quote "(table 0x1_0000_0000 0x1_0000_0000 funcref)") 33 | "i32 constant out of range" 34 | ) 35 | (assert_malformed 36 | (module quote "(table 0 0x1_0000_0000 funcref)") 37 | "i32 constant out of range" 38 | ) 39 | 40 | 41 | ;; Duplicate table identifiers 42 | 43 | (assert_malformed (module quote 44 | "(table $foo 1 funcref)" 45 | "(table $foo 1 funcref)") 46 | "duplicate table") 47 | (assert_malformed (module quote 48 | "(import \"\" \"\" (table $foo 1 funcref))" 49 | "(table $foo 1 funcref)") 50 | "duplicate table") 51 | (assert_malformed (module quote 52 | "(import \"\" \"\" (table $foo 1 funcref))" 53 | "(import \"\" \"\" (table $foo 1 funcref))") 54 | "duplicate table") 55 | -------------------------------------------------------------------------------- /test/core/table_fill.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (table $t 10 externref) 3 | 4 | (func (export "fill") (param $i i32) (param $r externref) (param $n i32) 5 | (table.fill $t (local.get $i) (local.get $r) (local.get $n)) 6 | ) 7 | 8 | (func (export "fill-abbrev") (param $i i32) (param $r externref) (param $n i32) 9 | (table.fill (local.get $i) (local.get $r) (local.get $n)) 10 | ) 11 | 12 | (func (export "get") (param $i i32) (result externref) 13 | (table.get $t (local.get $i)) 14 | ) 15 | ) 16 | 17 | (assert_return (invoke "get" (i32.const 1)) (ref.null extern)) 18 | (assert_return (invoke "get" (i32.const 2)) (ref.null extern)) 19 | (assert_return (invoke "get" (i32.const 3)) (ref.null extern)) 20 | (assert_return (invoke "get" (i32.const 4)) (ref.null extern)) 21 | (assert_return (invoke "get" (i32.const 5)) (ref.null extern)) 22 | 23 | (assert_return (invoke "fill" (i32.const 2) (ref.extern 1) (i32.const 3))) 24 | (assert_return (invoke "get" (i32.const 1)) (ref.null extern)) 25 | (assert_return (invoke "get" (i32.const 2)) (ref.extern 1)) 26 | (assert_return (invoke "get" (i32.const 3)) (ref.extern 1)) 27 | (assert_return (invoke "get" (i32.const 4)) (ref.extern 1)) 28 | (assert_return (invoke "get" (i32.const 5)) (ref.null extern)) 29 | 30 | (assert_return (invoke "fill" (i32.const 4) (ref.extern 2) (i32.const 2))) 31 | (assert_return (invoke "get" (i32.const 3)) (ref.extern 1)) 32 | (assert_return (invoke "get" (i32.const 4)) (ref.extern 2)) 33 | (assert_return (invoke "get" (i32.const 5)) (ref.extern 2)) 34 | (assert_return (invoke "get" (i32.const 6)) (ref.null extern)) 35 | 36 | (assert_return (invoke "fill" (i32.const 4) (ref.extern 3) (i32.const 0))) 37 | (assert_return (invoke "get" (i32.const 3)) (ref.extern 1)) 38 | (assert_return (invoke "get" (i32.const 4)) (ref.extern 2)) 39 | (assert_return (invoke "get" (i32.const 5)) (ref.extern 2)) 40 | 41 | (assert_return (invoke "fill" (i32.const 8) (ref.extern 4) (i32.const 2))) 42 | (assert_return (invoke "get" (i32.const 7)) (ref.null extern)) 43 | (assert_return (invoke "get" (i32.const 8)) (ref.extern 4)) 44 | (assert_return (invoke "get" (i32.const 9)) (ref.extern 4)) 45 | 46 | (assert_return (invoke "fill-abbrev" (i32.const 9) (ref.null extern) (i32.const 1))) 47 | (assert_return (invoke "get" (i32.const 8)) (ref.extern 4)) 48 | (assert_return (invoke "get" (i32.const 9)) (ref.null extern)) 49 | 50 | (assert_return (invoke "fill" (i32.const 10) (ref.extern 5) (i32.const 0))) 51 | (assert_return (invoke "get" (i32.const 9)) (ref.null extern)) 52 | 53 | (assert_trap 54 | (invoke "fill" (i32.const 8) (ref.extern 6) (i32.const 3)) 55 | "out of bounds table access" 56 | ) 57 | (assert_return (invoke "get" (i32.const 7)) (ref.null extern)) 58 | (assert_return (invoke "get" (i32.const 8)) (ref.extern 4)) 59 | (assert_return (invoke "get" (i32.const 9)) (ref.null extern)) 60 | 61 | (assert_trap 62 | (invoke "fill" (i32.const 11) (ref.null extern) (i32.const 0)) 63 | "out of bounds table access" 64 | ) 65 | 66 | (assert_trap 67 | (invoke "fill" (i32.const 11) (ref.null extern) (i32.const 10)) 68 | "out of bounds table access" 69 | ) 70 | 71 | 72 | ;; Type errors 73 | 74 | (assert_invalid 75 | (module 76 | (table $t 10 externref) 77 | (func $type-index-value-length-empty-vs-i32-i32 78 | (table.fill $t) 79 | ) 80 | ) 81 | "type mismatch" 82 | ) 83 | (assert_invalid 84 | (module 85 | (table $t 10 externref) 86 | (func $type-index-empty-vs-i32 87 | (table.fill $t (ref.null extern) (i32.const 1)) 88 | ) 89 | ) 90 | "type mismatch" 91 | ) 92 | (assert_invalid 93 | (module 94 | (table $t 10 externref) 95 | (func $type-value-empty-vs 96 | (table.fill $t (i32.const 1) (i32.const 1)) 97 | ) 98 | ) 99 | "type mismatch" 100 | ) 101 | (assert_invalid 102 | (module 103 | (table $t 10 externref) 104 | (func $type-length-empty-vs-i32 105 | (table.fill $t (i32.const 1) (ref.null extern)) 106 | ) 107 | ) 108 | "type mismatch" 109 | ) 110 | (assert_invalid 111 | (module 112 | (table $t 0 externref) 113 | (func $type-index-f32-vs-i32 114 | (table.fill $t (f32.const 1) (ref.null extern) (i32.const 1)) 115 | ) 116 | ) 117 | "type mismatch" 118 | ) 119 | (assert_invalid 120 | (module 121 | (table $t 0 funcref) 122 | (func $type-value-vs-funcref (param $r externref) 123 | (table.fill $t (i32.const 1) (local.get $r) (i32.const 1)) 124 | ) 125 | ) 126 | "type mismatch" 127 | ) 128 | (assert_invalid 129 | (module 130 | (table $t 0 externref) 131 | (func $type-length-f32-vs-i32 132 | (table.fill $t (i32.const 1) (ref.null extern) (f32.const 1)) 133 | ) 134 | ) 135 | "type mismatch" 136 | ) 137 | 138 | (assert_invalid 139 | (module 140 | (table $t1 1 externref) 141 | (table $t2 1 funcref) 142 | (func $type-value-externref-vs-funcref-multi (param $r externref) 143 | (table.fill $t2 (i32.const 0) (local.get $r) (i32.const 1)) 144 | ) 145 | ) 146 | "type mismatch" 147 | ) 148 | 149 | (assert_invalid 150 | (module 151 | (table $t 1 externref) 152 | (func $type-result-empty-vs-num (result i32) 153 | (table.fill $t (i32.const 0) (ref.null extern) (i32.const 1)) 154 | ) 155 | ) 156 | "type mismatch" 157 | ) 158 | -------------------------------------------------------------------------------- /test/core/table_get.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (table $t2 2 externref) 3 | (table $t3 3 funcref) 4 | (elem (table $t3) (i32.const 1) func $dummy) 5 | (func $dummy) 6 | 7 | (func (export "init") (param $r externref) 8 | (table.set $t2 (i32.const 1) (local.get $r)) 9 | (table.set $t3 (i32.const 2) (table.get $t3 (i32.const 1))) 10 | ) 11 | 12 | (func (export "get-externref") (param $i i32) (result externref) 13 | (table.get (local.get $i)) 14 | ) 15 | (func $f3 (export "get-funcref") (param $i i32) (result funcref) 16 | (table.get $t3 (local.get $i)) 17 | ) 18 | 19 | (func (export "is_null-funcref") (param $i i32) (result i32) 20 | (ref.is_null (call $f3 (local.get $i))) 21 | ) 22 | ) 23 | 24 | (invoke "init" (ref.extern 1)) 25 | 26 | (assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern)) 27 | (assert_return (invoke "get-externref" (i32.const 1)) (ref.extern 1)) 28 | 29 | (assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func)) 30 | (assert_return (invoke "is_null-funcref" (i32.const 1)) (i32.const 0)) 31 | (assert_return (invoke "is_null-funcref" (i32.const 2)) (i32.const 0)) 32 | 33 | (assert_trap (invoke "get-externref" (i32.const 2)) "out of bounds table access") 34 | (assert_trap (invoke "get-funcref" (i32.const 3)) "out of bounds table access") 35 | (assert_trap (invoke "get-externref" (i32.const -1)) "out of bounds table access") 36 | (assert_trap (invoke "get-funcref" (i32.const -1)) "out of bounds table access") 37 | 38 | 39 | ;; Type errors 40 | 41 | (assert_invalid 42 | (module 43 | (table $t 10 externref) 44 | (func $type-index-empty-vs-i32 (result externref) 45 | (table.get $t) 46 | ) 47 | ) 48 | "type mismatch" 49 | ) 50 | (assert_invalid 51 | (module 52 | (table $t 10 externref) 53 | (func $type-index-f32-vs-i32 (result externref) 54 | (table.get $t (f32.const 1)) 55 | ) 56 | ) 57 | "type mismatch" 58 | ) 59 | 60 | (assert_invalid 61 | (module 62 | (table $t 10 externref) 63 | (func $type-result-externref-vs-empty 64 | (table.get $t (i32.const 0)) 65 | ) 66 | ) 67 | "type mismatch" 68 | ) 69 | (assert_invalid 70 | (module 71 | (table $t 10 externref) 72 | (func $type-result-externref-vs-funcref (result funcref) 73 | (table.get $t (i32.const 1)) 74 | ) 75 | ) 76 | "type mismatch" 77 | ) 78 | 79 | (assert_invalid 80 | (module 81 | (table $t1 1 funcref) 82 | (table $t2 1 externref) 83 | (func $type-result-externref-vs-funcref-multi (result funcref) 84 | (table.get $t2 (i32.const 0)) 85 | ) 86 | ) 87 | "type mismatch" 88 | ) 89 | -------------------------------------------------------------------------------- /test/core/table_grow.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (table $t 0 externref) 3 | 4 | (func (export "get") (param $i i32) (result externref) (table.get $t (local.get $i))) 5 | (func (export "set") (param $i i32) (param $r externref) (table.set $t (local.get $i) (local.get $r))) 6 | 7 | (func (export "grow") (param $sz i32) (param $init externref) (result i32) 8 | (table.grow $t (local.get $init) (local.get $sz)) 9 | ) 10 | (func (export "grow-abbrev") (param $sz i32) (param $init externref) (result i32) 11 | (table.grow (local.get $init) (local.get $sz)) 12 | ) 13 | (func (export "size") (result i32) (table.size $t)) 14 | ) 15 | 16 | (assert_return (invoke "size") (i32.const 0)) 17 | (assert_trap (invoke "set" (i32.const 0) (ref.extern 2)) "out of bounds table access") 18 | (assert_trap (invoke "get" (i32.const 0)) "out of bounds table access") 19 | 20 | (assert_return (invoke "grow" (i32.const 1) (ref.null extern)) (i32.const 0)) 21 | (assert_return (invoke "size") (i32.const 1)) 22 | (assert_return (invoke "get" (i32.const 0)) (ref.null extern)) 23 | (assert_return (invoke "set" (i32.const 0) (ref.extern 2))) 24 | (assert_return (invoke "get" (i32.const 0)) (ref.extern 2)) 25 | (assert_trap (invoke "set" (i32.const 1) (ref.extern 2)) "out of bounds table access") 26 | (assert_trap (invoke "get" (i32.const 1)) "out of bounds table access") 27 | 28 | (assert_return (invoke "grow-abbrev" (i32.const 4) (ref.extern 3)) (i32.const 1)) 29 | (assert_return (invoke "size") (i32.const 5)) 30 | (assert_return (invoke "get" (i32.const 0)) (ref.extern 2)) 31 | (assert_return (invoke "set" (i32.const 0) (ref.extern 2))) 32 | (assert_return (invoke "get" (i32.const 0)) (ref.extern 2)) 33 | (assert_return (invoke "get" (i32.const 1)) (ref.extern 3)) 34 | (assert_return (invoke "get" (i32.const 4)) (ref.extern 3)) 35 | (assert_return (invoke "set" (i32.const 4) (ref.extern 4))) 36 | (assert_return (invoke "get" (i32.const 4)) (ref.extern 4)) 37 | (assert_trap (invoke "set" (i32.const 5) (ref.extern 2)) "out of bounds table access") 38 | (assert_trap (invoke "get" (i32.const 5)) "out of bounds table access") 39 | 40 | 41 | ;; Reject growing to size outside i32 value range 42 | (module 43 | (table $t 0x10 funcref) 44 | (elem declare func $f) 45 | (func $f (export "grow") (result i32) 46 | (table.grow $t (ref.func $f) (i32.const 0xffff_fff0)) 47 | ) 48 | ) 49 | 50 | (assert_return (invoke "grow") (i32.const -1)) 51 | 52 | 53 | (module 54 | (table $t 0 externref) 55 | (func (export "grow") (param i32) (result i32) 56 | (table.grow $t (ref.null extern) (local.get 0)) 57 | ) 58 | ) 59 | 60 | (assert_return (invoke "grow" (i32.const 0)) (i32.const 0)) 61 | (assert_return (invoke "grow" (i32.const 1)) (i32.const 0)) 62 | (assert_return (invoke "grow" (i32.const 0)) (i32.const 1)) 63 | (assert_return (invoke "grow" (i32.const 2)) (i32.const 1)) 64 | (assert_return (invoke "grow" (i32.const 800)) (i32.const 3)) 65 | 66 | 67 | (module 68 | (table $t 0 10 externref) 69 | (func (export "grow") (param i32) (result i32) 70 | (table.grow $t (ref.null extern) (local.get 0)) 71 | ) 72 | ) 73 | 74 | (assert_return (invoke "grow" (i32.const 0)) (i32.const 0)) 75 | (assert_return (invoke "grow" (i32.const 1)) (i32.const 0)) 76 | (assert_return (invoke "grow" (i32.const 1)) (i32.const 1)) 77 | (assert_return (invoke "grow" (i32.const 2)) (i32.const 2)) 78 | (assert_return (invoke "grow" (i32.const 6)) (i32.const 4)) 79 | (assert_return (invoke "grow" (i32.const 0)) (i32.const 10)) 80 | (assert_return (invoke "grow" (i32.const 1)) (i32.const -1)) 81 | (assert_return (invoke "grow" (i32.const 0x10000)) (i32.const -1)) 82 | 83 | 84 | (module 85 | (table $t 10 funcref) 86 | (func (export "grow") (param i32) (result i32) 87 | (table.grow $t (ref.null func) (local.get 0)) 88 | ) 89 | (elem declare func 1) 90 | (func (export "check-table-null") (param i32 i32) (result funcref) 91 | (local funcref) 92 | (local.set 2 (ref.func 1)) 93 | (block 94 | (loop 95 | (local.set 2 (table.get $t (local.get 0))) 96 | (br_if 1 (i32.eqz (ref.is_null (local.get 2)))) 97 | (br_if 1 (i32.ge_u (local.get 0) (local.get 1))) 98 | (local.set 0 (i32.add (local.get 0) (i32.const 1))) 99 | (br_if 0 (i32.le_u (local.get 0) (local.get 1))) 100 | ) 101 | ) 102 | (local.get 2) 103 | ) 104 | ) 105 | 106 | (assert_return (invoke "check-table-null" (i32.const 0) (i32.const 9)) (ref.null func)) 107 | (assert_return (invoke "grow" (i32.const 10)) (i32.const 10)) 108 | (assert_return (invoke "check-table-null" (i32.const 0) (i32.const 19)) (ref.null func)) 109 | 110 | 111 | ;; Type errors 112 | 113 | (assert_invalid 114 | (module 115 | (table $t 0 externref) 116 | (func $type-init-size-empty-vs-i32-externref (result i32) 117 | (table.grow $t) 118 | ) 119 | ) 120 | "type mismatch" 121 | ) 122 | (assert_invalid 123 | (module 124 | (table $t 0 externref) 125 | (func $type-size-empty-vs-i32 (result i32) 126 | (table.grow $t (ref.null extern)) 127 | ) 128 | ) 129 | "type mismatch" 130 | ) 131 | (assert_invalid 132 | (module 133 | (table $t 0 externref) 134 | (func $type-init-empty-vs-externref (result i32) 135 | (table.grow $t (i32.const 1)) 136 | ) 137 | ) 138 | "type mismatch" 139 | ) 140 | (assert_invalid 141 | (module 142 | (table $t 0 externref) 143 | (func $type-size-f32-vs-i32 (result i32) 144 | (table.grow $t (ref.null extern) (f32.const 1)) 145 | ) 146 | ) 147 | "type mismatch" 148 | ) 149 | (assert_invalid 150 | (module 151 | (table $t 0 funcref) 152 | (func $type-init-externref-vs-funcref (param $r externref) (result i32) 153 | (table.grow $t (local.get $r) (i32.const 1)) 154 | ) 155 | ) 156 | "type mismatch" 157 | ) 158 | 159 | (assert_invalid 160 | (module 161 | (table $t 1 externref) 162 | (func $type-result-i32-vs-empty 163 | (table.grow $t (ref.null extern) (i32.const 0)) 164 | ) 165 | ) 166 | "type mismatch" 167 | ) 168 | (assert_invalid 169 | (module 170 | (table $t 1 externref) 171 | (func $type-result-i32-vs-f32 (result f32) 172 | (table.grow $t (ref.null extern) (i32.const 0)) 173 | ) 174 | ) 175 | "type mismatch" 176 | ) 177 | -------------------------------------------------------------------------------- /test/core/table_set.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (table $t2 1 externref) 3 | (table $t3 2 funcref) 4 | (elem (table $t3) (i32.const 1) func $dummy) 5 | (func $dummy) 6 | 7 | (func (export "get-externref") (param $i i32) (result externref) 8 | (table.get $t2 (local.get $i)) 9 | ) 10 | (func $f3 (export "get-funcref") (param $i i32) (result funcref) 11 | (table.get $t3 (local.get $i)) 12 | ) 13 | 14 | (func (export "set-externref") (param $i i32) (param $r externref) 15 | (table.set (local.get $i) (local.get $r)) 16 | ) 17 | (func (export "set-funcref") (param $i i32) (param $r funcref) 18 | (table.set $t3 (local.get $i) (local.get $r)) 19 | ) 20 | (func (export "set-funcref-from") (param $i i32) (param $j i32) 21 | (table.set $t3 (local.get $i) (table.get $t3 (local.get $j))) 22 | ) 23 | 24 | (func (export "is_null-funcref") (param $i i32) (result i32) 25 | (ref.is_null (call $f3 (local.get $i))) 26 | ) 27 | ) 28 | 29 | (assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern)) 30 | (assert_return (invoke "set-externref" (i32.const 0) (ref.extern 1))) 31 | (assert_return (invoke "get-externref" (i32.const 0)) (ref.extern 1)) 32 | (assert_return (invoke "set-externref" (i32.const 0) (ref.null extern))) 33 | (assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern)) 34 | 35 | (assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func)) 36 | (assert_return (invoke "set-funcref-from" (i32.const 0) (i32.const 1))) 37 | (assert_return (invoke "is_null-funcref" (i32.const 0)) (i32.const 0)) 38 | (assert_return (invoke "set-funcref" (i32.const 0) (ref.null func))) 39 | (assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func)) 40 | 41 | (assert_trap (invoke "set-externref" (i32.const 2) (ref.null extern)) "out of bounds table access") 42 | (assert_trap (invoke "set-funcref" (i32.const 3) (ref.null func)) "out of bounds table access") 43 | (assert_trap (invoke "set-externref" (i32.const -1) (ref.null extern)) "out of bounds table access") 44 | (assert_trap (invoke "set-funcref" (i32.const -1) (ref.null func)) "out of bounds table access") 45 | 46 | (assert_trap (invoke "set-externref" (i32.const 2) (ref.extern 0)) "out of bounds table access") 47 | (assert_trap (invoke "set-funcref-from" (i32.const 3) (i32.const 1)) "out of bounds table access") 48 | (assert_trap (invoke "set-externref" (i32.const -1) (ref.extern 0)) "out of bounds table access") 49 | (assert_trap (invoke "set-funcref-from" (i32.const -1) (i32.const 1)) "out of bounds table access") 50 | 51 | 52 | ;; Type errors 53 | 54 | (assert_invalid 55 | (module 56 | (table $t 10 externref) 57 | (func $type-index-value-empty-vs-i32-externref 58 | (table.set $t) 59 | ) 60 | ) 61 | "type mismatch" 62 | ) 63 | (assert_invalid 64 | (module 65 | (table $t 10 externref) 66 | (func $type-index-empty-vs-i32 67 | (table.set $t (ref.null extern)) 68 | ) 69 | ) 70 | "type mismatch" 71 | ) 72 | (assert_invalid 73 | (module 74 | (table $t 10 externref) 75 | (func $type-value-empty-vs-externref 76 | (table.set $t (i32.const 1)) 77 | ) 78 | ) 79 | "type mismatch" 80 | ) 81 | (assert_invalid 82 | (module 83 | (table $t 10 externref) 84 | (func $type-size-f32-vs-i32 85 | (table.set $t (f32.const 1) (ref.null extern)) 86 | ) 87 | ) 88 | "type mismatch" 89 | ) 90 | (assert_invalid 91 | (module 92 | (table $t 10 funcref) 93 | (func $type-value-externref-vs-funcref (param $r externref) 94 | (table.set $t (i32.const 1) (local.get $r)) 95 | ) 96 | ) 97 | "type mismatch" 98 | ) 99 | 100 | (assert_invalid 101 | (module 102 | (table $t1 1 externref) 103 | (table $t2 1 funcref) 104 | (func $type-value-externref-vs-funcref-multi (param $r externref) 105 | (table.set $t2 (i32.const 0) (local.get $r)) 106 | ) 107 | ) 108 | "type mismatch" 109 | ) 110 | 111 | (assert_invalid 112 | (module 113 | (table $t 10 externref) 114 | (func $type-result-empty-vs-num (result i32) 115 | (table.set $t (i32.const 0) (ref.null extern)) 116 | ) 117 | ) 118 | "type mismatch" 119 | ) 120 | -------------------------------------------------------------------------------- /test/core/table_size.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (table $t0 0 externref) 3 | (table $t1 1 externref) 4 | (table $t2 0 2 externref) 5 | (table $t3 3 8 externref) 6 | 7 | (func (export "size-t0") (result i32) table.size) 8 | (func (export "size-t1") (result i32) (table.size $t1)) 9 | (func (export "size-t2") (result i32) (table.size $t2)) 10 | (func (export "size-t3") (result i32) (table.size $t3)) 11 | 12 | (func (export "grow-t0") (param $sz i32) 13 | (drop (table.grow $t0 (ref.null extern) (local.get $sz))) 14 | ) 15 | (func (export "grow-t1") (param $sz i32) 16 | (drop (table.grow $t1 (ref.null extern) (local.get $sz))) 17 | ) 18 | (func (export "grow-t2") (param $sz i32) 19 | (drop (table.grow $t2 (ref.null extern) (local.get $sz))) 20 | ) 21 | (func (export "grow-t3") (param $sz i32) 22 | (drop (table.grow $t3 (ref.null extern) (local.get $sz))) 23 | ) 24 | ) 25 | 26 | (assert_return (invoke "size-t0") (i32.const 0)) 27 | (assert_return (invoke "grow-t0" (i32.const 1))) 28 | (assert_return (invoke "size-t0") (i32.const 1)) 29 | (assert_return (invoke "grow-t0" (i32.const 4))) 30 | (assert_return (invoke "size-t0") (i32.const 5)) 31 | (assert_return (invoke "grow-t0" (i32.const 0))) 32 | (assert_return (invoke "size-t0") (i32.const 5)) 33 | 34 | (assert_return (invoke "size-t1") (i32.const 1)) 35 | (assert_return (invoke "grow-t1" (i32.const 1))) 36 | (assert_return (invoke "size-t1") (i32.const 2)) 37 | (assert_return (invoke "grow-t1" (i32.const 4))) 38 | (assert_return (invoke "size-t1") (i32.const 6)) 39 | (assert_return (invoke "grow-t1" (i32.const 0))) 40 | (assert_return (invoke "size-t1") (i32.const 6)) 41 | 42 | (assert_return (invoke "size-t2") (i32.const 0)) 43 | (assert_return (invoke "grow-t2" (i32.const 3))) 44 | (assert_return (invoke "size-t2") (i32.const 0)) 45 | (assert_return (invoke "grow-t2" (i32.const 1))) 46 | (assert_return (invoke "size-t2") (i32.const 1)) 47 | (assert_return (invoke "grow-t2" (i32.const 0))) 48 | (assert_return (invoke "size-t2") (i32.const 1)) 49 | (assert_return (invoke "grow-t2" (i32.const 4))) 50 | (assert_return (invoke "size-t2") (i32.const 1)) 51 | (assert_return (invoke "grow-t2" (i32.const 1))) 52 | (assert_return (invoke "size-t2") (i32.const 2)) 53 | 54 | (assert_return (invoke "size-t3") (i32.const 3)) 55 | (assert_return (invoke "grow-t3" (i32.const 1))) 56 | (assert_return (invoke "size-t3") (i32.const 4)) 57 | (assert_return (invoke "grow-t3" (i32.const 3))) 58 | (assert_return (invoke "size-t3") (i32.const 7)) 59 | (assert_return (invoke "grow-t3" (i32.const 0))) 60 | (assert_return (invoke "size-t3") (i32.const 7)) 61 | (assert_return (invoke "grow-t3" (i32.const 2))) 62 | (assert_return (invoke "size-t3") (i32.const 7)) 63 | (assert_return (invoke "grow-t3" (i32.const 1))) 64 | (assert_return (invoke "size-t3") (i32.const 8)) 65 | 66 | 67 | ;; Type errors 68 | 69 | (assert_invalid 70 | (module 71 | (table $t 1 externref) 72 | (func $type-result-i32-vs-empty 73 | (table.size $t) 74 | ) 75 | ) 76 | "type mismatch" 77 | ) 78 | (assert_invalid 79 | (module 80 | (table $t 1 externref) 81 | (func $type-result-i32-vs-f32 (result f32) 82 | (table.size $t) 83 | ) 84 | ) 85 | "type mismatch" 86 | ) 87 | -------------------------------------------------------------------------------- /test/core/token.wast: -------------------------------------------------------------------------------- 1 | ;; Test tokenization 2 | 3 | (assert_malformed 4 | (module quote "(func (drop (i32.const0)))") 5 | "unknown operator" 6 | ) 7 | (assert_malformed 8 | (module quote "(func br 0drop)") 9 | "unknown operator" 10 | ) 11 | -------------------------------------------------------------------------------- /test/core/tokens.wast: -------------------------------------------------------------------------------- 1 | ;; Tokens can be delimited by parentheses 2 | 3 | (module 4 | (func(nop)) 5 | ) 6 | (module 7 | (func (nop)nop) 8 | ) 9 | (module 10 | (func nop(nop)) 11 | ) 12 | (module 13 | (func(nop)(nop)) 14 | ) 15 | (module 16 | (func $f(nop)) 17 | ) 18 | (module 19 | (func br 0(nop)) 20 | ) 21 | (module 22 | (table 1 funcref) 23 | (func) 24 | (elem (i32.const 0)0) 25 | ) 26 | (module 27 | (table 1 funcref) 28 | (func $f) 29 | (elem (i32.const 0)$f) 30 | ) 31 | (module 32 | (memory 1) 33 | (data (i32.const 0)"a") 34 | ) 35 | (module 36 | (import "spectest" "print"(func)) 37 | ) 38 | 39 | 40 | ;; Tokens can be delimited by comments 41 | 42 | (module 43 | (func;;bla 44 | ) 45 | ) 46 | (module 47 | (func (nop);;bla 48 | ) 49 | ) 50 | (module 51 | (func nop;;bla 52 | ) 53 | ) 54 | (module 55 | (func $f;;bla 56 | ) 57 | ) 58 | (module 59 | (func br 0;;bla 60 | ) 61 | ) 62 | (module 63 | (data "a";;bla 64 | ) 65 | ) 66 | 67 | 68 | ;; Space required between symbols and non-parenthesis tokens 69 | 70 | (module 71 | (func (block $l (i32.const 0) (br_table 0 $l))) 72 | ) 73 | (assert_malformed 74 | (module quote 75 | "(func (block $l (i32.const 0) (br_table 0$l)))" 76 | ) 77 | "unknown operator" 78 | ) 79 | 80 | (module 81 | (func (block $l (i32.const 0) (br_table $l 0))) 82 | ) 83 | (assert_malformed 84 | (module quote 85 | "(func (block $l (i32.const 0) (br_table $l0)))" 86 | ) 87 | "unknown label" 88 | ) 89 | 90 | (module 91 | (func (block $l (i32.const 0) (br_table $l $l))) 92 | ) 93 | (assert_malformed 94 | (module quote 95 | "(func (block $l (i32.const 0) (br_table $l$l)))" 96 | ) 97 | "unknown label" 98 | ) 99 | 100 | (module 101 | (func (block $l0 (i32.const 0) (br_table $l0))) 102 | ) 103 | (module 104 | (func (block $l$l (i32.const 0) (br_table $l$l))) 105 | ) 106 | 107 | 108 | ;; Space required between strings and non-parenthesis tokens 109 | 110 | (module 111 | (data "a") 112 | ) 113 | (assert_malformed 114 | (module quote 115 | "(data\"a\")" 116 | ) 117 | "unknown operator" 118 | ) 119 | 120 | (module 121 | (data $l "a") 122 | ) 123 | (assert_malformed 124 | (module quote 125 | "(data $l\"a\")" 126 | ) 127 | "unknown operator" 128 | ) 129 | 130 | (module 131 | (data $l " a") 132 | ) 133 | (assert_malformed 134 | (module quote 135 | "(data $l\" a\")" 136 | ) 137 | "unknown operator" 138 | ) 139 | 140 | (module 141 | (data $l "a ") 142 | ) 143 | (assert_malformed 144 | (module quote 145 | "(data $l\"a \")" 146 | ) 147 | "unknown operator" 148 | ) 149 | 150 | (module 151 | (data $l "a " "b") 152 | ) 153 | (assert_malformed 154 | (module quote 155 | "(data $l\"a \"\"b\")" 156 | ) 157 | "unknown operator" 158 | ) 159 | 160 | (module 161 | (data $l "") 162 | ) 163 | (assert_malformed 164 | (module quote 165 | "(data $l\"\")" 166 | ) 167 | "unknown operator" 168 | ) 169 | 170 | (module 171 | (data $l " ") 172 | ) 173 | (assert_malformed 174 | (module quote 175 | "(data $l\" \")" 176 | ) 177 | "unknown operator" 178 | ) 179 | 180 | (module 181 | (data $l " ") 182 | ) 183 | (assert_malformed 184 | (module quote 185 | "(data $l\" \")" 186 | ) 187 | "unknown operator" 188 | ) 189 | 190 | (module 191 | (data "a" "b") 192 | ) 193 | (assert_malformed 194 | (module quote 195 | "(data \"a\"\"b\")" 196 | ) 197 | "unknown operator" 198 | ) 199 | 200 | (module 201 | (data "a" " b") 202 | ) 203 | (assert_malformed 204 | (module quote 205 | "(data \"a\"\" b\")" 206 | ) 207 | "unknown operator" 208 | ) 209 | 210 | (module 211 | (data "a " "b") 212 | ) 213 | (assert_malformed 214 | (module quote 215 | "(data \"a \"\"b\")" 216 | ) 217 | "unknown operator" 218 | ) 219 | 220 | (module 221 | (data "" "") 222 | ) 223 | (assert_malformed 224 | (module quote 225 | "(data \"\"\"\")" 226 | ) 227 | "unknown operator" 228 | ) 229 | 230 | (module 231 | (data "" " ") 232 | ) 233 | (assert_malformed 234 | (module quote 235 | "(data \"\"\" \")" 236 | ) 237 | "unknown operator" 238 | ) 239 | 240 | (module 241 | (data " " "") 242 | ) 243 | (assert_malformed 244 | (module quote 245 | "(data \" \"\"\")" 246 | ) 247 | "unknown operator" 248 | ) 249 | 250 | 251 | (assert_malformed 252 | (module quote 253 | "(func \"a\"x)" 254 | ) 255 | "unknown operator" 256 | ) 257 | (assert_malformed 258 | (module quote 259 | "(func \"a\"0)" 260 | ) 261 | "unknown operator" 262 | ) 263 | (assert_malformed 264 | (module quote 265 | "(func 0\"a\")" 266 | ) 267 | "unknown operator" 268 | ) 269 | (assert_malformed 270 | (module quote 271 | "(func \"a\"$x)" 272 | ) 273 | "unknown operator" 274 | ) 275 | -------------------------------------------------------------------------------- /test/core/traps.wast: -------------------------------------------------------------------------------- 1 | ;; Test that traps are preserved even in instructions which might otherwise 2 | ;; be dead-code-eliminated. These functions all perform an operation and 3 | ;; discard its return value. 4 | 5 | (module 6 | (func (export "no_dce.i32.div_s") (param $x i32) (param $y i32) 7 | (drop (i32.div_s (local.get $x) (local.get $y)))) 8 | (func (export "no_dce.i32.div_u") (param $x i32) (param $y i32) 9 | (drop (i32.div_u (local.get $x) (local.get $y)))) 10 | (func (export "no_dce.i64.div_s") (param $x i64) (param $y i64) 11 | (drop (i64.div_s (local.get $x) (local.get $y)))) 12 | (func (export "no_dce.i64.div_u") (param $x i64) (param $y i64) 13 | (drop (i64.div_u (local.get $x) (local.get $y)))) 14 | ) 15 | 16 | (assert_trap (invoke "no_dce.i32.div_s" (i32.const 1) (i32.const 0)) "integer divide by zero") 17 | (assert_trap (invoke "no_dce.i32.div_u" (i32.const 1) (i32.const 0)) "integer divide by zero") 18 | (assert_trap (invoke "no_dce.i64.div_s" (i64.const 1) (i64.const 0)) "integer divide by zero") 19 | (assert_trap (invoke "no_dce.i64.div_u" (i64.const 1) (i64.const 0)) "integer divide by zero") 20 | (assert_trap (invoke "no_dce.i32.div_s" (i32.const 0x80000000) (i32.const -1)) "integer overflow") 21 | (assert_trap (invoke "no_dce.i64.div_s" (i64.const 0x8000000000000000) (i64.const -1)) "integer overflow") 22 | 23 | (module 24 | (func (export "no_dce.i32.rem_s") (param $x i32) (param $y i32) 25 | (drop (i32.rem_s (local.get $x) (local.get $y)))) 26 | (func (export "no_dce.i32.rem_u") (param $x i32) (param $y i32) 27 | (drop (i32.rem_u (local.get $x) (local.get $y)))) 28 | (func (export "no_dce.i64.rem_s") (param $x i64) (param $y i64) 29 | (drop (i64.rem_s (local.get $x) (local.get $y)))) 30 | (func (export "no_dce.i64.rem_u") (param $x i64) (param $y i64) 31 | (drop (i64.rem_u (local.get $x) (local.get $y)))) 32 | ) 33 | 34 | (assert_trap (invoke "no_dce.i32.rem_s" (i32.const 1) (i32.const 0)) "integer divide by zero") 35 | (assert_trap (invoke "no_dce.i32.rem_u" (i32.const 1) (i32.const 0)) "integer divide by zero") 36 | (assert_trap (invoke "no_dce.i64.rem_s" (i64.const 1) (i64.const 0)) "integer divide by zero") 37 | (assert_trap (invoke "no_dce.i64.rem_u" (i64.const 1) (i64.const 0)) "integer divide by zero") 38 | 39 | (module 40 | (func (export "no_dce.i32.trunc_f32_s") (param $x f32) (drop (i32.trunc_f32_s (local.get $x)))) 41 | (func (export "no_dce.i32.trunc_f32_u") (param $x f32) (drop (i32.trunc_f32_u (local.get $x)))) 42 | (func (export "no_dce.i32.trunc_f64_s") (param $x f64) (drop (i32.trunc_f64_s (local.get $x)))) 43 | (func (export "no_dce.i32.trunc_f64_u") (param $x f64) (drop (i32.trunc_f64_u (local.get $x)))) 44 | (func (export "no_dce.i64.trunc_f32_s") (param $x f32) (drop (i64.trunc_f32_s (local.get $x)))) 45 | (func (export "no_dce.i64.trunc_f32_u") (param $x f32) (drop (i64.trunc_f32_u (local.get $x)))) 46 | (func (export "no_dce.i64.trunc_f64_s") (param $x f64) (drop (i64.trunc_f64_s (local.get $x)))) 47 | (func (export "no_dce.i64.trunc_f64_u") (param $x f64) (drop (i64.trunc_f64_u (local.get $x)))) 48 | ) 49 | 50 | (assert_trap (invoke "no_dce.i32.trunc_f32_s" (f32.const nan)) "invalid conversion to integer") 51 | (assert_trap (invoke "no_dce.i32.trunc_f32_u" (f32.const nan)) "invalid conversion to integer") 52 | (assert_trap (invoke "no_dce.i32.trunc_f64_s" (f64.const nan)) "invalid conversion to integer") 53 | (assert_trap (invoke "no_dce.i32.trunc_f64_u" (f64.const nan)) "invalid conversion to integer") 54 | (assert_trap (invoke "no_dce.i64.trunc_f32_s" (f32.const nan)) "invalid conversion to integer") 55 | (assert_trap (invoke "no_dce.i64.trunc_f32_u" (f32.const nan)) "invalid conversion to integer") 56 | (assert_trap (invoke "no_dce.i64.trunc_f64_s" (f64.const nan)) "invalid conversion to integer") 57 | (assert_trap (invoke "no_dce.i64.trunc_f64_u" (f64.const nan)) "invalid conversion to integer") 58 | 59 | (module 60 | (memory 1) 61 | 62 | (func (export "no_dce.i32.load") (param $i i32) (drop (i32.load (local.get $i)))) 63 | (func (export "no_dce.i32.load16_s") (param $i i32) (drop (i32.load16_s (local.get $i)))) 64 | (func (export "no_dce.i32.load16_u") (param $i i32) (drop (i32.load16_u (local.get $i)))) 65 | (func (export "no_dce.i32.load8_s") (param $i i32) (drop (i32.load8_s (local.get $i)))) 66 | (func (export "no_dce.i32.load8_u") (param $i i32) (drop (i32.load8_u (local.get $i)))) 67 | (func (export "no_dce.i64.load") (param $i i32) (drop (i64.load (local.get $i)))) 68 | (func (export "no_dce.i64.load32_s") (param $i i32) (drop (i64.load32_s (local.get $i)))) 69 | (func (export "no_dce.i64.load32_u") (param $i i32) (drop (i64.load32_u (local.get $i)))) 70 | (func (export "no_dce.i64.load16_s") (param $i i32) (drop (i64.load16_s (local.get $i)))) 71 | (func (export "no_dce.i64.load16_u") (param $i i32) (drop (i64.load16_u (local.get $i)))) 72 | (func (export "no_dce.i64.load8_s") (param $i i32) (drop (i64.load8_s (local.get $i)))) 73 | (func (export "no_dce.i64.load8_u") (param $i i32) (drop (i64.load8_u (local.get $i)))) 74 | (func (export "no_dce.f32.load") (param $i i32) (drop (f32.load (local.get $i)))) 75 | (func (export "no_dce.f64.load") (param $i i32) (drop (f64.load (local.get $i)))) 76 | ) 77 | 78 | (assert_trap (invoke "no_dce.i32.load" (i32.const 65536)) "out of bounds memory access") 79 | (assert_trap (invoke "no_dce.i32.load16_s" (i32.const 65536)) "out of bounds memory access") 80 | (assert_trap (invoke "no_dce.i32.load16_u" (i32.const 65536)) "out of bounds memory access") 81 | (assert_trap (invoke "no_dce.i32.load8_s" (i32.const 65536)) "out of bounds memory access") 82 | (assert_trap (invoke "no_dce.i32.load8_u" (i32.const 65536)) "out of bounds memory access") 83 | (assert_trap (invoke "no_dce.i64.load" (i32.const 65536)) "out of bounds memory access") 84 | (assert_trap (invoke "no_dce.i64.load32_s" (i32.const 65536)) "out of bounds memory access") 85 | (assert_trap (invoke "no_dce.i64.load32_u" (i32.const 65536)) "out of bounds memory access") 86 | (assert_trap (invoke "no_dce.i64.load16_s" (i32.const 65536)) "out of bounds memory access") 87 | (assert_trap (invoke "no_dce.i64.load16_u" (i32.const 65536)) "out of bounds memory access") 88 | (assert_trap (invoke "no_dce.i64.load8_s" (i32.const 65536)) "out of bounds memory access") 89 | (assert_trap (invoke "no_dce.i64.load8_u" (i32.const 65536)) "out of bounds memory access") 90 | (assert_trap (invoke "no_dce.f32.load" (i32.const 65536)) "out of bounds memory access") 91 | (assert_trap (invoke "no_dce.f64.load" (i32.const 65536)) "out of bounds memory access") 92 | -------------------------------------------------------------------------------- /test/core/type.wast: -------------------------------------------------------------------------------- 1 | ;; Test type definitions 2 | 3 | (module 4 | (type (func)) 5 | (type $t (func)) 6 | 7 | (type (func (param i32))) 8 | (type (func (param $x i32))) 9 | (type (func (result i32))) 10 | (type (func (param i32) (result i32))) 11 | (type (func (param $x i32) (result i32))) 12 | 13 | (type (func (param f32 f64))) 14 | (type (func (result i64 f32))) 15 | (type (func (param i32 i64) (result f32 f64))) 16 | 17 | (type (func (param f32) (param f64))) 18 | (type (func (param $x f32) (param f64))) 19 | (type (func (param f32) (param $y f64))) 20 | (type (func (param $x f32) (param $y f64))) 21 | (type (func (result i64) (result f32))) 22 | (type (func (param i32) (param i64) (result f32) (result f64))) 23 | (type (func (param $x i32) (param $y i64) (result f32) (result f64))) 24 | 25 | (type (func (param f32 f64) (param $x i32) (param f64 i32 i32))) 26 | (type (func (result i64 i64 f32) (result f32 i32))) 27 | (type 28 | (func (param i32 i32) (param i64 i32) (result f32 f64) (result f64 i32)) 29 | ) 30 | 31 | (type (func (param) (param $x f32) (param) (param) (param f64 i32) (param))) 32 | (type 33 | (func (result) (result) (result i64 i64) (result) (result f32) (result)) 34 | ) 35 | (type 36 | (func 37 | (param i32 i32) (param i64 i32) (param) (param $x i32) (param) 38 | (result) (result f32 f64) (result f64 i32) (result) 39 | ) 40 | ) 41 | ) 42 | 43 | (assert_malformed 44 | (module quote "(type (func (result i32) (param i32)))") 45 | "unexpected token" 46 | ) 47 | (assert_malformed 48 | (module quote "(type (func (result $x i32)))") 49 | "unexpected token" 50 | ) 51 | -------------------------------------------------------------------------------- /test/core/unreached-valid.wast: -------------------------------------------------------------------------------- 1 | (module 2 | 3 | ;; Check that both sides of the select are evaluated 4 | (func (export "select-trap-left") (param $cond i32) (result i32) 5 | (select (unreachable) (i32.const 0) (local.get $cond)) 6 | ) 7 | (func (export "select-trap-right") (param $cond i32) (result i32) 8 | (select (i32.const 0) (unreachable) (local.get $cond)) 9 | ) 10 | 11 | (func (export "select-unreached") 12 | (unreachable) (select) 13 | (unreachable) (i32.const 0) (select) 14 | (unreachable) (i32.const 0) (i32.const 0) (select) 15 | (unreachable) (i32.const 0) (i32.const 0) (i32.const 0) (select) 16 | (unreachable) (f32.const 0) (i32.const 0) (select) 17 | (unreachable) 18 | ) 19 | 20 | (func (export "select_unreached_result_1") (result i32) 21 | (unreachable) (i32.add (select)) 22 | ) 23 | 24 | (func (export "select_unreached_result_2") (result i64) 25 | (unreachable) (i64.add (select (i64.const 0) (i32.const 0))) 26 | ) 27 | 28 | (func (export "unreachable-num") 29 | (unreachable) 30 | (select) 31 | (i32.eqz) 32 | (drop) 33 | ) 34 | (func (export "unreachable-ref") 35 | (unreachable) 36 | (select) 37 | (ref.is_null) 38 | (drop) 39 | ) 40 | ) 41 | 42 | (assert_trap (invoke "select-trap-left" (i32.const 1)) "unreachable") 43 | (assert_trap (invoke "select-trap-left" (i32.const 0)) "unreachable") 44 | (assert_trap (invoke "select-trap-right" (i32.const 1)) "unreachable") 45 | (assert_trap (invoke "select-trap-right" (i32.const 0)) "unreachable") 46 | 47 | ;; Validation after unreachable 48 | 49 | (module 50 | (func (export "meet-bottom") 51 | (block (result f64) 52 | (block (result f32) 53 | (unreachable) 54 | (br_table 0 1 1 (i32.const 1)) 55 | ) 56 | (drop) 57 | (f64.const 0) 58 | ) 59 | (drop) 60 | ) 61 | ) 62 | 63 | (assert_trap (invoke "meet-bottom") "unreachable") 64 | -------------------------------------------------------------------------------- /test/crc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | uint16_t crcu8(uint8_t data, uint16_t crc) { 6 | uint8_t i = 0; 7 | uint8_t x16 = 0; 8 | uint8_t carry = 0; 9 | 10 | for (i = 0; i < 8; i++) { 11 | x16 = (uint8_t)((data & 1) ^ ((uint8_t)crc & 1)); 12 | data >>= 1; 13 | 14 | if (x16 == 1) { 15 | crc ^= 0x4002; 16 | carry = 1; 17 | } else 18 | carry = 0; 19 | crc >>= 1; 20 | if (carry) 21 | crc |= 0x8000; 22 | else 23 | crc &= 0x7fff; 24 | } 25 | return crc; 26 | } 27 | 28 | uint16_t crcu16(uint16_t newval, uint16_t crc) { 29 | crc = crcu8((uint8_t)(newval), crc); 30 | crc = crcu8((uint8_t)((newval) >> 8), crc); 31 | return crc; 32 | } 33 | 34 | uint16_t crc16(int16_t newval, uint16_t crc) { 35 | return crcu16((uint16_t)newval, crc); 36 | } 37 | 38 | uint16_t crcu32(uint32_t newval, uint16_t crc) { 39 | crc = crc16((int16_t)newval, crc); 40 | crc = crc16((int16_t)(newval >> 16), crc); 41 | return crc; 42 | } 43 | 44 | int main() { 45 | printf("%" PRIu16 "\n", crcu32(0xFAFFBADD, 0)); 46 | } -------------------------------------------------------------------------------- /test/fib.lua: -------------------------------------------------------------------------------- 1 | local function fib(n) 2 | if n < 2 then 3 | return n 4 | else 5 | return fib(n-2) + fib(n-1) 6 | end 7 | end 8 | 9 | print(fib(tonumber(arg[1]))) -------------------------------------------------------------------------------- /test/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | printf("Hello %s!\n", "World"); 5 | } -------------------------------------------------------------------------------- /test/names.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func $fib (export "fib") (param $x i32) (result i32) 3 | (if (result i32) (i32.lt_s (local.get $x) (i32.const 2)) 4 | (then 5 | (local.get $x)) 6 | (else 7 | (i32.add 8 | (call $fib (i32.sub (local.get $x) (i32.const 1))) 9 | (call $fib (i32.sub (local.get $x) (i32.const 2)))))))) 10 | 11 | (assert_return (invoke "fib" (i32.const 0)) (i32.const 0)) 12 | (assert_return (invoke "fib" (i32.const 1)) (i32.const 1)) 13 | (assert_return (invoke "fib" (i32.const 2)) (i32.const 1)) 14 | (assert_return (invoke "fib" (i32.const 3)) (i32.const 2)) 15 | (assert_return (invoke "fib" (i32.const 4)) (i32.const 3)) 16 | (assert_return (invoke "fib" (i32.const 5)) (i32.const 5)) 17 | (assert_return (invoke "fib" (i32.const 6)) (i32.const 8)) 18 | (assert_return (invoke "fib" (i32.const 7)) (i32.const 13)) 19 | (assert_return (invoke "fib" (i32.const 8)) (i32.const 21)) 20 | (assert_return (invoke "fib" (i32.const 9)) (i32.const 34)) 21 | (assert_return (invoke "fib" (i32.const 10)) (i32.const 55)) 22 | (assert_return (invoke "fib" (i32.const 11)) (i32.const 89)) 23 | (assert_return (invoke "fib" (i32.const 12)) (i32.const 144)) 24 | (assert_return (invoke "fib" (i32.const 13)) (i32.const 233)) 25 | (assert_return (invoke "fib" (i32.const 14)) (i32.const 377)) 26 | (assert_return (invoke "fib" (i32.const 15)) (i32.const 610)) -------------------------------------------------------------------------------- /test/nest.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func (export "no_nest") (param $x i32) (result i32) 3 | local.get $x 4 | if (result i32) 5 | i32.const 1 6 | else 7 | i32.const 0 8 | end) 9 | (func (export "full_nest") (param $x i32) (result i32) 10 | (if (result i32) (local.get $x) 11 | (then 12 | (i32.const 1)) 13 | (else 14 | (i32.const 0))))) 15 | 16 | (assert_return (invoke "no_nest" (i32.const 0)) (i32.const 0)) 17 | (assert_return (invoke "no_nest" (i32.const 1)) (i32.const 1)) 18 | (assert_return (invoke "no_nest" (i32.const 2)) (i32.const 1)) 19 | 20 | (assert_return (invoke "full_nest" (i32.const 0)) (i32.const 0)) 21 | (assert_return (invoke "full_nest" (i32.const 1)) (i32.const 1)) 22 | (assert_return (invoke "full_nest" (i32.const 2)) (i32.const 1)) -------------------------------------------------------------------------------- /test/test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | int main(int argc, char **argv) { 6 | printf("argc = %i\n", argc); 7 | for (int i = 0; i < argc; i++) { 8 | printf("strlen(argv[%i]) = %i\n", i, (int) strlen(argv[i])); 9 | } 10 | printf("argv[%i] = %p\n", argc, argv[argc]); 11 | } 12 | -------------------------------------------------------------------------------- /test/tree.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define N 16 6 | 7 | struct tree_t; 8 | typedef struct tree_t tree_t; 9 | 10 | struct tree_t { 11 | ptrdiff_t n; 12 | tree_t *pair; 13 | }; 14 | 15 | tree_t make_tree(ptrdiff_t item, ptrdiff_t depth) { 16 | if (depth != 0) { 17 | tree_t *pair = malloc(sizeof(tree_t) * 2); 18 | pair[0] = make_tree(item * 2 - 1, depth - 1); 19 | pair[1] = make_tree(item * 2, depth - 1); 20 | return (tree_t){ 21 | .n = item, 22 | .pair = pair, 23 | }; 24 | } else { 25 | return (tree_t){ 26 | .n = item, 27 | }; 28 | } 29 | } 30 | 31 | ptrdiff_t item_check(tree_t tree) { 32 | if (tree.pair != NULL) { 33 | return tree.n + item_check(tree.pair[0]) - item_check(tree.pair[1]); 34 | } else { 35 | return tree.n; 36 | } 37 | } 38 | 39 | void del_tree(tree_t tree) { 40 | if (tree.pair != NULL) { 41 | del_tree(tree.pair[0]); 42 | del_tree(tree.pair[1]); 43 | free(tree.pair); 44 | } 45 | } 46 | 47 | int main() { 48 | ptrdiff_t min = 4; 49 | ptrdiff_t max = min - 2; 50 | if (max < N) { 51 | max = N; 52 | } 53 | 54 | tree_t str = make_tree(0, max + 1); 55 | printf("%zi\n", item_check(str)); 56 | del_tree(str); 57 | 58 | tree_t tree = make_tree(0, max); 59 | 60 | for (ptrdiff_t depth = min; depth < max; depth += 2) { 61 | ptrdiff_t iters = 1 << (max - depth + min); 62 | ptrdiff_t check = 0; 63 | for (size_t i = 0; i < iters; i++) { 64 | tree_t ta = make_tree(1, depth); 65 | check += item_check(ta); 66 | del_tree(ta); 67 | tree_t tb = make_tree(-1, depth); 68 | check += item_check(tb); 69 | del_tree(tb); 70 | } 71 | printf("%zi\n", check); 72 | } 73 | 74 | printf("%zi\n", item_check(tree)); 75 | del_tree(tree); 76 | } 77 | -------------------------------------------------------------------------------- /test/tree.lua: -------------------------------------------------------------------------------- 1 | -- The Computer Language Benchmarks Game 2 | -- http://shootout.alioth.debian.org/ 3 | -- contributed by Mike Pall 4 | 5 | local function BottomUpTree(item, depth) 6 | if depth > 0 then 7 | local i = item + item 8 | depth = depth - 1 9 | local left, right = BottomUpTree(i-1, depth), BottomUpTree(i, depth) 10 | return { item, left, right } 11 | else 12 | return { item } 13 | end 14 | end 15 | 16 | local function ItemCheck(tree) 17 | if tree[2] then 18 | return tree[1] + ItemCheck(tree[2]) - ItemCheck(tree[3]) 19 | else 20 | return tree[1] 21 | end 22 | end 23 | 24 | local function Main(N) 25 | local mindepth = 4 26 | local maxdepth = mindepth + 2 27 | if maxdepth < N then maxdepth = N end 28 | 29 | do 30 | local stretchdepth = maxdepth + 1 31 | local stretchtree = BottomUpTree(0, stretchdepth) 32 | print(ItemCheck(stretchtree)) 33 | end 34 | 35 | local longlivedtree = BottomUpTree(0, maxdepth) 36 | 37 | for depth=mindepth,maxdepth,2 do 38 | local iterations = 2 ^ (maxdepth - depth + mindepth) 39 | local check = 0 40 | for i=1,iterations do 41 | check = check + ItemCheck(BottomUpTree(1, depth)) + ItemCheck(BottomUpTree(-1, depth)) 42 | end 43 | print(check) 44 | end 45 | 46 | print(ItemCheck(longlivedtree)) 47 | end 48 | 49 | Main(16) --------------------------------------------------------------------------------