├── .gitignore
├── .travis.yml
├── LICENSE
├── NOTES.md
├── README.md
├── build-d8.sh
├── example1.wasm
├── example2.wasm
├── exec
└── Main.hs
├── out
└── .gitkeep
├── package.yaml
├── scripts
└── ci.sh
├── shell
├── src
└── Language
│ ├── Wasm.hs
│ └── Wasm
│ ├── Binary.hs
│ ├── Core.hs
│ ├── Entry.hs
│ ├── Lexer.x
│ ├── Monad.hs
│ ├── Parser.y
│ ├── Position.hs
│ ├── Pretty.hs
│ └── Syntax.hs
├── stack.yaml
├── test.js
├── test.sh
├── tests
├── Test.hs
├── failing
│ ├── address.wast
│ ├── align.wast
│ ├── binary.wast
│ ├── block.wast
│ ├── br.wast
│ ├── br_if.wast
│ ├── br_table.wast
│ ├── break-drop.wast
│ ├── call.wast
│ ├── call_indirect.wast
│ ├── comments.wast
│ ├── const.wast
│ ├── conversions.wast
│ ├── custom_section.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
│ ├── get_local.wast
│ ├── globals.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
│ ├── loop.wast
│ ├── memory.wast
│ ├── memory_redundancy.wast
│ ├── memory_trap.wast
│ ├── names.wast
│ ├── nop.wast
│ ├── resizing.wast
│ ├── return.wast
│ ├── select.wast
│ ├── set_local.wast
│ ├── simple.wast.golden.wasm
│ ├── simple.wast.out.wasm
│ ├── skip-stack-guard-page.wast
│ ├── stack.wast
│ ├── start.wast
│ ├── store_retval.wast
│ ├── switch.wast
│ ├── tee_local.wast
│ ├── token.wast
│ ├── traps.wast
│ ├── type.wast
│ ├── typecheck.wast
│ ├── unreachable.wast
│ ├── unreached-invalid.wast
│ ├── unwind.wast
│ ├── utf8-custom-section-id.wast
│ ├── utf8-import-field.wast
│ ├── utf8-import-module.wast
│ └── utf8-invalid-encoding.wast
└── spec
│ ├── golden
│ ├── .gitkeep
│ ├── fac.wasm
│ └── simple.wasm
│ ├── input
│ ├── add.wast
│ ├── empty.wast
│ ├── fac.wast
│ ├── log.wast
│ ├── shared.wast
│ └── simple.wast
│ └── output
│ └── .gitkeep
├── wasm.cabal
└── watch
/.gitignore:
--------------------------------------------------------------------------------
1 | *.sw[po]
2 | *.o
3 | *.so
4 | cabal.sandbox.config
5 | .cabal-sandbox
6 | dist/
7 | *.hi
8 | *.o
9 | includes
10 | .history
11 | .stack-work
12 | Setup.hs
13 | tests/spec/output
14 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: generic
2 | sudo: false
3 |
4 | cache:
5 | directories:
6 | - $HOME/.stack
7 | - $HOME/.cabal
8 | - $HOME/.ghc
9 |
10 | matrix:
11 | fast_finish: true
12 | include:
13 | - env: BUILD=stack STACK_BUILD_MODE="test" STACK_BUILD_ARGS="--bench --no-run-benchmarks" STACK_ARGS="" STACK_YAML=stack.yaml
14 | compiler: ": #stack 8.0.1"
15 | addons: {apt: {packages: [libgmp-dev]}}
16 | - env: BUILD=stack STACK_BUILD_MODE="test" STACK_BUILD_ARGS="--bench --no-run-benchmarks" STACK_ARGS="--resolver nightly" STACK_YAML=stack.yaml
17 | compiler: ": #stack 8.0.2"
18 | addons: {apt: {packages: [libgmp-dev]}}
19 | #- env: BUILD=cabal CABALVER=1.24 GHCVER=8.0.1
20 | # compiler: ": #GHC 8.0.1"
21 | # addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.1], sources: [hvr-ghc]}}
22 |
23 | before_install:
24 | - chmod +x scripts/ci.sh
25 | - mkdir -p ~/.local/bin
26 | - unset CC
27 | - case "$BUILD" in
28 | stack)
29 | export PATH=$HOME/.local/bin:/opt/ghc/$GHCVER/bin:$PATH;
30 | travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack';;
31 | cabal)
32 | export PATH=$HOME/.cabal/bin:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH;;
33 | esac
34 |
35 | install:
36 | - case "$BUILD" in
37 | cabal)
38 | travis_retry cabal update -v;;
39 | esac
40 | - scripts/ci.sh "install"
41 |
42 | script:
43 | - scripts/ci.sh "script"
44 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 Stephen Diehl
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included
12 | in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/NOTES.md:
--------------------------------------------------------------------------------
1 | Notes
2 | =====
3 |
4 | * [Design](https://github.com/WebAssembly/design)
5 | * [Semantics](https://github.com/WebAssembly/design/blob/master/AstSemantics.md)
6 | * [Reference Implementation](https://github.com/WebAssembly/spec/tree/64822f7137e26c0b101ecba9cb1cd93d416c2c74/ml-proto)
7 | * [Binary Encoding](http://webassembly.org/docs/binary-encoding/)
8 | * [ilwasm](https://github.com/WebAssembly/ilwasm)
9 | * [binaryren](https://github.com/WebAssembly/binaryen)
10 | * [wassembler](https://github.com/ncbray/wassembler)
11 | * [demo](https://ncbray.github.io/wassembler/)
12 | * [backend prototype](https://github.com/ncbray/wassembler/blob/master/v8/backend.js)
13 | * [WasmExplorer](https://mbebenita.github.io/WasmExplorer/)
14 | * [Javascript API](http://webassembly.org/docs/js/)
15 | * [Spec](https://webassembly.github.io/spec/index.html)
16 |
17 | **Binary Protocol**
18 |
19 | * [wasm.h](https://github.com/WebAssembly/binaryen/blob/master/src/wasm.h)
20 | * [wasm-binary.h](https://github.com/WebAssembly/binaryen/blob/master/src/wasm-binary.h)
21 |
22 | **Chrome**
23 |
24 | * [v8 wasm](https://github.com/v8/v8/tree/master/src/wasm)
25 |
26 | As of Chrome 56 the flag `#enable-webassembly` can be enabled to add support for
27 | WebAssembly.
28 |
29 | **Firefox**
30 |
31 | * [BaldrMonkey: land initial wasm compilation and testing functions](https://bugzilla.mozilla.org/show_bug.cgi?id=1234985)
32 |
33 | #### Goals
34 |
35 | * Parse WebAssembly textual AST
36 | * Read binary format
37 | * Emit binary format
38 | * Pretty print textual AST
39 | * Verify soundness of code
40 | * Interpreter
41 | * High level code generation API for retargeting
42 | * Translation to [LLVM IR backend](http://reviews.llvm.org/D10569)
43 |
44 | ### Build with `stack` (recommended)
45 |
46 | ```bash
47 | $ git clone https://github.com/sdiehl/wasm
48 | $ cd wasm
49 | $ stack install
50 | ```
51 |
52 | ```bash
53 | $ wasm fac.wasm
54 | ```
55 |
56 | ### Build with `cabal`
57 |
58 | ```bash
59 | $ git clone https://github.com/sdiehl/wasm
60 | $ cd wasm
61 |
62 | $ cabal sandbox init
63 | $ cabal install
64 | ```
65 |
66 | ### How to Run Test Suite
67 |
68 | ```bash
69 | $ stack test
70 | ```
71 |
72 | ### How to Run inside GHCi
73 |
74 |
75 | ```bash
76 | $ stack ghci wasm
77 | ```
78 |
79 | #### Building v8
80 |
81 | In Chrome:
82 |
83 | ```javascript
84 | WebAssembly.compile(new Uint8Array(
85 | `00 61 73 6d 0d 00 00 00 01 09 02 60 00 00 60 01
86 | 7f 01 7f 03 03 02 00 01 05 04 01 00 80 01 07 07
87 | 01 03 66 6f 6f 00 01 08 01 00 0a 3a 02 02 00 0b
88 | 35 01 01 7f 20 00 41 04 6c 21 01 03 40 01 01 01
89 | 0b 03 7f 41 01 0b 20 01 41 e4 00 6c 41 cd 02 20
90 | 01 1b 21 01 41 00 20 01 36 02 00 41 00 21 01 41
91 | 00 28 02 00 0f 0b 0b 0e 01 00 41 00 0b 08 00 00
92 | 00 00 2c 00 00 00`.split(/[\s\r\n]+/g).map(v => parseInt(v, 16))
93 | )).then(mod => {
94 | let m = new WebAssembly.Instance(mod)
95 | console.log('foo(1) =>', m.exports.foo(1))
96 | console.log('foo(2) =>', m.exports.foo(2))
97 | console.log('foo(3) =>', m.exports.foo(3))
98 | })
99 | ```
100 |
101 | In V8:
102 |
103 | ```bash
104 | $ git clone git@github.com:v8/v8.git
105 | $ make native wasm=on
106 |
107 | $ out/native/v8 --expose-wasm
108 | V8 version 4.9.0 (candidate)
109 | d8> buffer = readbuffer('test.bin');
110 | [object ArrayBufferr
111 | d8> module = WASM.instantiateModule(buffer, {});
112 | {memory: [object ArrayBuffer], test: function test() { [native code] }}
113 | d8> module.test()
114 | 3
115 | ```
116 |
117 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Haskell WebAssembly
6 | -------------------
7 |
8 | [](https://travis-ci.org/haskell-wasm/wasm)
9 |
10 | A WebAssembly AST, parser, and assembler in Haskell for use in functional compiler backends
11 | targeting WebAssembly.
12 |
13 | Warning, still a *big* work in progress.
14 |
15 | Codebase
16 | --------
17 |
18 | Core modules
19 |
20 | * [Entry](https://github.com/sdiehl/wasm/blob/master/src/Language/Wasm/Entry.hs) - Driver
21 | * [Syntax](https://github.com/sdiehl/wasm/blob/master/src/Language/Wasm/Syntax.hs) - Frontend AST
22 | * [Parser](https://github.com/sdiehl/wasm/blob/master/src/Language/Wasm/Parser.y) - Parser
23 | * [Lexer](https://github.com/sdiehl/wasm/blob/master/src/Language/Wasm/Lexer.x) - Lexer
24 | * [Pretty](https://github.com/sdiehl/wasm/blob/master/src/Language/Wasm/Pretty.hs) - Textual Format
25 | * [Binary](https://github.com/sdiehl/wasm/blob/master/src/Language/Wasm/Binary.hs) - Binary Format
26 | * [Test](https://github.com/sdiehl/wasm/blob/master/src/Test.hs) - Test suite
27 |
28 | Usage
29 | -----
30 |
31 | ```haskell
32 | import Language.Wasm.Syntax
33 | import Language.Wasm.Binary
34 | import Language.Wasm.Parser
35 | ```
36 |
37 |
--------------------------------------------------------------------------------
/build-d8.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -o nounset
3 | set -o errexit
4 |
5 | config=Release
6 |
7 | while [[ $# > 0 ]]; do
8 | flag="$1"
9 | case $flag in
10 | --debug)
11 | config=Debug
12 | ;;
13 | *)
14 | echo "unknown arg ${flag}"
15 | ;;
16 | esac
17 | shift
18 | done
19 |
20 | SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
21 | ROOT_DIR="$(dirname "${SCRIPT_DIR}")"
22 |
23 | cd ${ROOT_DIR}/third_party/v8
24 |
25 | if [[ ! -d depot_tools ]]; then
26 | echo "Cloning depot_tools"
27 | git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
28 | fi
29 |
30 | export PATH=$PWD/depot_tools:$PATH
31 | gclient sync
32 |
33 | # Don't use the CC from the environment; v8 doesn't seem to build properly with
34 | # it.
35 | unset CC
36 | cd v8
37 | GYP_GENERATORS=ninja build/gyp_v8 -Dv8_wasm=1
38 | time ninja -C out/${config} d8
39 |
--------------------------------------------------------------------------------
/example1.wasm:
--------------------------------------------------------------------------------
1 | (module
2 | (export "test" 0)
3 | (func (result i32)
4 | (i32.add (i32.const 25) (i32.const 25)))
5 | )
6 |
--------------------------------------------------------------------------------
/example2.wasm:
--------------------------------------------------------------------------------
1 | (module
2 |
3 | (func $foo (result i32) (i32.const 0))
4 |
5 | (func f
6 | (i32.const 0)
7 | (i32.const -2147483648)
8 | (i32.const 4294967295)
9 | (i32.const -0x80000000)
10 | (i32.const 0xffffffff)
11 |
12 | (i64.const 0)
13 | (i64.const -9223372036854775808)
14 | (i64.const 18446744073709551615)
15 | (i64.const -0x8000000000000000)
16 | (i64.const 0xffffffffffffffff)
17 | )
18 |
19 | (func $add (param $x f32) (param $y f32) (result f32) (f32.add (get_local $x) (get_local $y)))
20 | (func $sub (param $x f32) (param $y f32) (result f32) (f32.sub (get_local $x) (get_local $y)))
21 | (func $mul (param $x f32) (param $y f32) (result f32) (f32.mul (get_local $x) (get_local $y)))
22 | (func $div (param $x f32) (param $y f32) (result f32) (f32.div (get_local $x) (get_local $y)))
23 | (func $sqrt (param $x f32) (result f32) (f32.sqrt (get_local $x)))
24 | (func $min (param $x f32) (param $y f32) (result f32) (f32.min (get_local $x) (get_local $y)))
25 | (func $max (param $x f32) (param $y f32) (result f32) (f32.max (get_local $x) (get_local $y)))
26 | (func $ceil (param $x f32) (result f32) (f32.ceil (get_local $x)))
27 | (func $floor (param $x f32) (result f32) (f32.floor (get_local $x)))
28 | (func $trunc (param $x f32) (result f32) (f32.trunc (get_local $x)))
29 | (func $nearest (param $x f32) (result f32) (f32.nearest (get_local $x)))
30 | (func $abs (param $x f32) (result f32) (f32.abs (get_local $x)))
31 | (func $neg (param $x f32) (result f32) (f32.neg (get_local $x)))
32 | (func $copysign (param $x f32) (param $y f32) (result f32) (f32.copysign (get_local $x) (get_local $y)))
33 |
34 | (func f (param x i64) (result i64)
35 |
36 | (if_else (i64.eq (get_local 0) (i64.const 0))
37 | (i64.const 1)
38 | (i64.mul (get_local 0) (call 0 (i64.sub (get_local 0) (i64.const 1))))
39 | )
40 |
41 | )
42 |
43 | (func $fac-rec (param $n i64) (result i64)
44 | (if_else (i64.eq (get_local $n) (i64.const 0))
45 | (i64.const 1)
46 | (i64.mul
47 | (get_local $n)
48 | (call $fac-rec (i64.sub (get_local $n) (i64.const 1)))
49 | )
50 | )
51 | )
52 |
53 | (func f (param a i64) (result i64)
54 | (set_local 1 (get_local 0))
55 | (set_local 2 (i64.const 1))
56 | (block
57 | (loop
58 | (if_else
59 | (i64.eq (get_local 1) (i64.const 0))
60 | (br 1)
61 | (block
62 | (set_local 2 (i64.mul (get_local 1) (get_local 2)))
63 | (set_local 1 (i64.sub (get_local 1) (i64.const 1)))
64 | )
65 | )
66 | (br 0)
67 | )
68 | )
69 | (return (get_local 2))
70 | )
71 |
72 | ;; foo
73 | (func f (param i64) (result i64)
74 | (set_local 1 (get_local 0))
75 | (set_local 2 (i64.const 1))
76 | (block
77 | (loop
78 | (if_else
79 | (i64.eq (get_local 1) (i64.const 0))
80 | (br 1)
81 | (block
82 | (set_local 2 (i64.mul (get_local 1) (get_local 2)))
83 | (set_local 1 (i64.sub (get_local 1) (i64.const 1)))
84 | )
85 | )
86 | (br 0)
87 | )
88 | )
89 | (return (get_local 2))
90 | )
91 |
92 |
93 | )
94 |
--------------------------------------------------------------------------------
/exec/Main.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import qualified Language.Wasm.Entry as Entry
4 |
5 | main :: IO ()
6 | main = Entry.main
7 |
--------------------------------------------------------------------------------
/out/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdiehl/wasm/f81d757210a3fd0a5df08a26379359591a8f695e/out/.gitkeep
--------------------------------------------------------------------------------
/package.yaml:
--------------------------------------------------------------------------------
1 | name: wasm
2 | version: '0.1'
3 | author: Stephen Diehl
4 | maintainer: stephen.m.diehl@gmail.com
5 | license: MIT
6 | extra-source-files:
7 | - README.md
8 | - src/Language/Wasm/Parser.y
9 | - src/Language/Wasm/Lexer.x
10 | build-tools:
11 | - alex >=3.1.3
12 | - happy >=1.9.4
13 | dependencies:
14 | - base >=4.6 && <5.0
15 |
16 | library:
17 | source-dirs: src
18 | ghc-options:
19 | - -Wwarn
20 | - -fwarn-incomplete-patterns
21 | - -fwarn-unused-imports
22 | exposed-modules:
23 | - Language.Wasm.Core
24 | - Language.Wasm.Pretty
25 | - Language.Wasm.Syntax
26 | - Language.Wasm.Binary
27 | - Language.Wasm.Lexer
28 | - Language.Wasm.Parser
29 | - Language.Wasm.Entry
30 | other-modules:
31 | - Language.Wasm.Monad
32 | - Language.Wasm.Position
33 | dependencies:
34 | - array >= 0.5 && <0.6
35 | - text >= 1.1
36 | - bytestring >= 0.10
37 | - mtl >= 2.2 && <3.0
38 | - transformers >= 0.4 && <0.6
39 | - pretty >= 1.1 && <1.2
40 | - pretty-show >= 1.6 && <1.7
41 | - process >= 1.1
42 | - directory >= 1.2
43 | - containers >= 0.5 && <0.6
44 | - binary >= 0.7 && <0.9
45 | - cereal >= 0.4 && <0.6
46 | - ansi-wl-pprint >= 0.6 && <0.7
47 | - wl-pprint-text >= 1.0 && <2.0
48 | - optparse-applicative >= 0.11 && <0.15
49 | - pretty-hex >= 0.1
50 |
51 | executables:
52 | wasm:
53 | main: Main.hs
54 | source-dirs: exec
55 | dependencies:
56 | - wasm ==0.1
57 |
58 | tests:
59 | test:
60 | main: Test.hs
61 | source-dirs: tests
62 | dependencies:
63 | - wasm ==0.1
64 | - filepath >=1.3 && <1.5
65 | - text >=1.1 && <1.3
66 | - bytestring >=0.10 && <0.11
67 | - cereal >=0.4 && <0.6
68 | - tasty >=0.7
69 | - tasty-hunit >=0.4.1 && <0.10
70 | - tasty-golden >=2.2 && <2.4
71 | - pretty-hex >= 0.1
72 | - mtl ==2.2.1
73 |
--------------------------------------------------------------------------------
/scripts/ci.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 | set -x
5 |
6 | step="$1"
7 |
8 | echo "Running step $step ..."
9 |
10 | case "$step" in
11 | install)
12 | mkdir -p $HOME/.local/bin
13 | case "$BUILD" in
14 | stack)
15 | stack $STACK_ARGS setup --no-terminal
16 | stack $STACK_ARGS build --fast --only-snapshot --no-terminal
17 | ;;
18 | cabal)
19 | sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config;
20 | cabal new-build --enable-tests -j4 --dep wasm
21 | ;;
22 | esac
23 | ;;
24 | script)
25 | case "$BUILD" in
26 | stack)
27 | stack $STACK_ARGS $STACK_BUILD_MODE --fast --no-terminal --skip-ghc-check $STACK_BUILD_ARGS
28 | ;;
29 | cabal)
30 | cabal new-build --enable-tests -j4 --dep wasm
31 | ;;
32 | esac
33 | ;;
34 | *)
35 | echo "Bad step: $step"
36 | exit 1
37 | ;;
38 | esac
39 |
40 | echo "Completed $step ."
41 | exit 0
42 |
--------------------------------------------------------------------------------
/shell:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | stack repl wasm:lib --no-docker --silent $@
4 |
--------------------------------------------------------------------------------
/src/Language/Wasm.hs:
--------------------------------------------------------------------------------
1 | module Language.Wasm (
2 | module Language.Wasm.Syntax,
3 | parse,
4 | ) where
5 |
6 | import Language.Wasm.Syntax
7 | import Language.Wasm.Parser
8 |
--------------------------------------------------------------------------------
/src/Language/Wasm/Core.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE FunctionalDependencies #-}
2 | {-# LANGUAGE MultiParamTypeClasses #-}
3 |
4 | module Language.Wasm.Core (
5 | toCore,
6 | Func(..),
7 | Decl(..),
8 | Module(..),
9 | Import(..),
10 | Export(..),
11 |
12 | -- reexport common elements
13 | Syn.Name(..),
14 | Syn.Expr(..),
15 | Syn.Type(..),
16 | Syn.Value(..),
17 | {-Syn.Param(..),-}
18 | Syn.UnOp(..),
19 | Syn.BinOp(..),
20 | Syn.RelOp(..),
21 | Syn.ConvertOp(..)
22 | ) where
23 |
24 | import qualified Language.Wasm.Syntax as Syn
25 |
26 | data Decl
27 | = ModDecl Module
28 | | ExprDecl Syn.Expr
29 | deriving (Eq, Show)
30 |
31 | data Module = Module
32 | { _funcs :: [Func]
33 | , _imports :: [Import]
34 | , _exports :: [Export]
35 | } deriving (Eq, Show)
36 |
37 | data Func = Func
38 | { _fname :: Maybe Syn.Name
39 | , _params :: Int
40 | , _fbody :: [Syn.Expr]
41 | } deriving (Eq, Show)
42 |
43 | data Import
44 | = Import Syn.Name Syn.Name
45 | deriving (Eq, Show)
46 |
47 | data Export
48 | = Export Syn.Name Syn.Name
49 | deriving (Eq, Show)
50 |
51 | -------------------------------------------------------------------------------
52 | -- Conversion
53 | -------------------------------------------------------------------------------
54 |
55 | toCoreFunc :: Syn.Func -> Func
56 | toCoreFunc (Syn.Func ftype params _) = Func ftype (length params) body
57 | where
58 | body = [f | Syn.Body f <- params]
59 | result = head [f | Syn.Result f <- params]
60 | toCoreFunc _ = error "not impelemented"
61 |
62 | toCoreExport :: Syn.Func -> Export
63 | toCoreExport (Syn.Export fname val) = Export (undefined fname) (undefined fname)
64 | toCoreExport _ = error "not impelemented"
65 |
66 | toCoreImport :: Syn.Func -> Import
67 | toCoreImport _ = undefined
68 |
69 | toCoreMod :: Syn.Module -> Module
70 | toCoreMod (Syn.Module defs) = Module
71 | { _funcs = [toCoreFunc f | f@Syn.Func {} <- defs]
72 | , _imports = [toCoreImport f | f@Syn.Import {} <- defs]
73 | , _exports = [toCoreExport f | f@Syn.Export {} <- defs]
74 | }
75 |
76 | toCoreDecl :: Syn.Decl -> Decl
77 | toCoreDecl (Syn.ModDecl mod) = ModDecl (toCoreMod mod)
78 | toCoreDecl (Syn.ExprDecl exp) = ExprDecl exp
79 |
80 | toCore = toCoreDecl
81 |
82 | {-toCore :: [Syn.Decl] -> [Decl]-}
83 | {-toCore = fmap toCoreDecl-}
84 |
--------------------------------------------------------------------------------
/src/Language/Wasm/Entry.hs:
--------------------------------------------------------------------------------
1 | module Language.Wasm.Entry(
2 | main,
3 | parse,
4 | ) where
5 |
6 | import Language.Wasm.Core (toCore)
7 | import Language.Wasm.Lexer
8 | import Language.Wasm.Monad
9 | import Language.Wasm.Parser
10 | import Language.Wasm.Pretty
11 | import Language.Wasm.Syntax
12 | import Language.Wasm.Binary
13 |
14 | import System.Environment
15 | import Text.PrettyPrint.ANSI.Leijen
16 | import qualified Hexdump
17 |
18 | parse :: String -> Either ParseError [Decl]
19 | parse fs = runParseM prog (scan fs)
20 |
21 | file :: FilePath -> IO (Either ParseError [Decl])
22 | file fname = parse `fmap` readFile fname
23 |
24 | main :: IO ()
25 | main = do
26 | args <- getArgs
27 | let input = case args of
28 | [input] -> input
29 | _ -> "example1.wasm"
30 |
31 | ast1 <- file input
32 | putStrLn $ show ast1
33 |
34 | case ast1 of
35 | Left err -> return ()
36 | Right [mod] -> do
37 | {-putStrLn $ "=== AST ==="-}
38 | putDoc $ pretty mod
39 | putStrLn $ "=== WAST ==="
40 | let bs = encode (toCore mod)
41 | putStrLn $ "=== HEX ==="
42 | putStrLn $ Hexdump.prettyHex bs
43 | return ()
44 | Right _ -> return ()
45 |
46 | putStrLn "Done"
47 | return ()
48 |
--------------------------------------------------------------------------------
/src/Language/Wasm/Lexer.x:
--------------------------------------------------------------------------------
1 | {
2 |
3 | {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
4 | {-# OPTIONS_GHC -fno-warn-name-shadowing #-}
5 | {-# OPTIONS_GHC -fno-warn-unused-binds #-}
6 | {-# OPTIONS_GHC -fno-warn-unused-imports #-}
7 | {-# OPTIONS_GHC -fno-warn-unused-matches #-}
8 | {-# OPTIONS_GHC -fno-warn-tabs #-}
9 |
10 | module Language.Wasm.Lexer
11 | ( module Language.Wasm.Position
12 | , Token(..)
13 | , ppToken
14 | , AlexInput
15 | , initialAlexInput
16 | , alexScan
17 | , alexGetByte
18 | , AlexReturn(..)
19 | , scan
20 | ) where
21 |
22 | import Data.Char (isAscii)
23 | import qualified Data.Char as Char
24 | import Data.Word (Word8)
25 |
26 | import Language.Wasm.Position
27 |
28 | }
29 |
30 | $digit = [0-9]
31 | $lower = [a-z]
32 | $upper = [A-Z]
33 | $alpha = [$lower $upper]
34 | $alphanum = [$alpha $digit]
35 | $idchar = [$alphanum \_ \-]
36 | $graphic = $printable # $white
37 | $asigil = [\$ $alpha]
38 |
39 | @negative = \-
40 | @signed = @negative ?
41 |
42 | $binit = 0-1
43 | $octit = 0-7
44 | $hexit = [0-9 A-F a-f]
45 |
46 | @decimal = $digit+
47 | @decimal = $digit+
48 | @binary = $binit+
49 | @octal = $octit+
50 | @hexadecimal = $hexit+
51 |
52 | @num = @decimal | 0[bB] @binary | 0[oO] @octal | 0[xX] @hexadecimal
53 |
54 | @gap = \\ $white+ \\
55 | @string = $graphic # [\"] | " " | @gap
56 |
57 | @nat = $digit+
58 | @real = $digit+ \. $digit+
59 | @ident = $asigil ($idchar* $alphanum)?
60 |
61 | @punct =
62 | "(" | ")" | "*" | "+" | "," | "-" | "->" | "." | ".." | "..." |
63 | "/" | "//" | "/=" | ":" | ":{" | ";" | "<" | "<-" | "<->" | "<=" |
64 | "=" | ">" | ">=" | "[" | "\\" | "]" | "^" | "{" | "}"
65 |
66 | @keywords =
67 | "module" | "func" | "export" | "nop" | "block" | "unreachable" |
68 | "param" | "result" | "i32" | "i64" | "f32" | "f64" | "if" |
69 | "if_else" | "br_if" | "loop" | "br" | "return" | "call" | "const" |
70 | "add" | "mul" | "sub" | "eq" | "div" | "get_local" | "set_local" |
71 | "grow_memory" | "memory_size" | "local" | "tableswitch" | "nan" |
72 | "infinity" | "neg" | "floor" | "trunc" | "nearest" | "sqrt" |
73 | "max" | "min" | "ceil" | "floor" | "copysign" | "abs" | "void"
74 |
75 | @key = @punct | @keywords
76 |
77 | tokens :-
78 |
79 | $white+;
80 | ";;".* { TComment }
81 | \" @string* \" { TString . read }
82 | @nat { TNat . read }
83 | 0[oO] @octal { TNat . read }
84 | 0[xX] @hexadecimal { TNat . read }
85 | @signed @decimal { TNat . read }
86 | @signed 0[xX] @hexadecimal { TNat . read }
87 | @real { TReal . read }
88 | @key { TKey }
89 | @ident { TIdent }
90 | . { TIllegal }
91 |
92 |
93 | {
94 |
95 | data Token
96 | = TIdent String -- ^ Name/identifier
97 | | TNat Integer -- ^ Natural number literal
98 | | TReal Double -- ^ Real number literal
99 | | TString String -- ^ String literal
100 | | TChar Char -- ^ Character literal
101 | | TKey String -- ^ Keyword or predefined symbol
102 | | TComment String -- ^ Comment string
103 | | TEnd -- ^ End of file
104 | | TIllegal String -- ^ Illegal character
105 | deriving (Show)
106 |
107 | ppToken :: Token -> String
108 | ppToken tkn =
109 | case tkn of
110 | TIdent s -> s
111 | TNat n -> show n
112 | TReal d -> show d
113 | TString s -> show s
114 | TChar c -> show c
115 | TKey s -> s
116 | TComment s -> s
117 | TEnd -> "END"
118 | TIllegal s -> "illegal " ++ show s
119 |
120 | type Text = String
121 |
122 | uncons :: Text -> Maybe (Char, Text)
123 | uncons (c : cs) = Just (c, cs)
124 | uncons "" = Nothing
125 |
126 | data AlexInput
127 | = Inp { alexPos :: !Position
128 | , alexInputPrevChar :: !Char
129 | , input :: !Text
130 | } deriving Show
131 |
132 | initialAlexInput :: Text -> AlexInput
133 | initialAlexInput t =
134 | Inp { alexPos = start
135 | , alexInputPrevChar = '\n'
136 | , input = t
137 | }
138 |
139 | alexGetByte :: AlexInput -> Maybe (Word8, AlexInput)
140 | alexGetByte i = do
141 | (c, rest) <- uncons (input i)
142 | let i' = i { alexPos = move (alexPos i) c, input = rest }
143 | b = byteForChar c
144 | return (b, i')
145 |
146 | byteForChar :: Char -> Word8
147 | byteForChar c
148 | | c <= '\6' = non_graphic
149 | | isAscii c = fromIntegral (Char.ord c)
150 | | otherwise = case Char.generalCategory c of
151 | Char.LowercaseLetter -> lower
152 | Char.OtherLetter -> lower
153 | Char.UppercaseLetter -> upper
154 | Char.TitlecaseLetter -> upper
155 | Char.DecimalNumber -> digit
156 | Char.OtherNumber -> digit
157 | Char.ConnectorPunctuation -> symbol
158 | Char.DashPunctuation -> symbol
159 | Char.OtherPunctuation -> symbol
160 | Char.MathSymbol -> symbol
161 | Char.CurrencySymbol -> symbol
162 | Char.ModifierSymbol -> symbol
163 | Char.OtherSymbol -> symbol
164 | Char.Space -> sp
165 | Char.ModifierLetter -> other
166 | Char.NonSpacingMark -> other
167 | Char.SpacingCombiningMark -> other
168 | Char.EnclosingMark -> other
169 | Char.LetterNumber -> other
170 | Char.OpenPunctuation -> other
171 | Char.ClosePunctuation -> other
172 | Char.InitialQuote -> other
173 | Char.FinalQuote -> tick
174 | _ -> non_graphic
175 | where
176 | non_graphic = 0
177 | upper = 1
178 | lower = 2
179 | digit = 3
180 | symbol = 4
181 | sp = 5
182 | other = 6
183 | tick = 7
184 |
185 | scan :: String -> [Token]
186 | scan str = go (initialAlexInput str) where
187 | go inp =
188 | case alexScan inp 0 of
189 | AlexEOF -> [TEnd]
190 | AlexError _ -> error "lexical error"
191 | AlexSkip inp' len -> go inp'
192 | AlexToken inp' len act -> act (take len (input inp)) : go inp'
193 |
194 | }
195 |
196 | -- vim: set filetype=alex:
197 |
--------------------------------------------------------------------------------
/src/Language/Wasm/Monad.hs:
--------------------------------------------------------------------------------
1 | module Language.Wasm.Monad where
2 |
3 | import Control.Monad (ap)
4 | {-import qualified Data.Char as Char-}
5 | {-import Data.Char (isAscii)-}
6 | {-import Data.Word (Word8)-}
7 |
8 | import Language.Wasm.Lexer
9 |
10 | -- | Parser monad state
11 | data S = S [String] [Token]
12 |
13 | data ParseError
14 | = ParseError String
15 | | ParseErrorEOF
16 | deriving Show
17 |
18 | -- | Parsing monad
19 | newtype ParseM a
20 | = ParseM { unParseM :: S -> Either ParseError (a, S) }
21 |
22 | runParseM :: ParseM a -> [Token] -> Either ParseError a
23 | runParseM m ts = fst <$> unParseM m (S cs ts')
24 | where (cs, ts') = splitCommentTokens ts
25 |
26 | instance Functor ParseM where
27 | fmap f m = ParseM $
28 | fmap (\(x, s') -> (f x, s')) . unParseM m
29 |
30 | instance Monad ParseM where
31 | return x = ParseM $ \s -> Right (x, s)
32 | m >>= k = ParseM $ \s -> do
33 | (x, s') <- unParseM m s
34 | unParseM (k x) s'
35 |
36 | instance Applicative ParseM where
37 | pure = return
38 | (<*>) = ap
39 |
40 | splitCommentTokens :: [Token] -> ([String], [Token])
41 | splitCommentTokens = go []
42 | where
43 | go cs (TComment c : ts) = go (c : cs) ts
44 | go cs ts = (reverse cs, ts)
45 |
46 | -- | Return the list of comment tokens at the current location
47 | getComments :: ParseM [String]
48 | getComments = ParseM $ \(S cs ts) -> Right (cs, S [] ts)
49 |
50 | -- | Return the next non-comment token
51 | nextNonCommentToken :: ParseM Token
52 | nextNonCommentToken = ParseM $ \(S _ ts) ->
53 | let (cs, ts') = splitCommentTokens ts in
54 | Right $ case ts' of
55 | (t : ts'') -> (t, S cs ts'')
56 | [] -> (TEnd, S cs ts')
57 |
58 | lexerP :: (Token -> ParseM a) -> ParseM a
59 | lexerP = (nextNonCommentToken >>=)
60 |
--------------------------------------------------------------------------------
/src/Language/Wasm/Parser.y:
--------------------------------------------------------------------------------
1 | {
2 |
3 | module Language.Wasm.Parser where
4 |
5 | import Language.Wasm.Monad
6 | import Language.Wasm.Lexer
7 | import Language.Wasm.Syntax
8 |
9 | import qualified Data.Text as T
10 |
11 | }
12 |
13 | %name prog prog
14 | %tokentype { Token }
15 | %monad { ParseM }
16 | %lexer { lexerP } { TEnd }
17 |
18 | %token
19 |
20 | ident { TIdent $$ }
21 | integer { TNat $$ }
22 | char { TChar $$ }
23 | str { TString $$ }
24 | real { TReal $$ }
25 |
26 | '(' { TKey "(" }
27 | ')' { TKey ")" }
28 | '.' { TKey "." }
29 |
30 | 'i32' { TKey "i32" }
31 | 'i64' { TKey "i64" }
32 | 'f32' { TKey "f32" }
33 | 'f64' { TKey "f64" }
34 | 'void' { TKey "void" }
35 |
36 | 'module' { TKey "module" }
37 | 'export' { TKey "export" }
38 | 'func' { TKey "func" }
39 | 'const' { TKey "const" }
40 | 'param' { TKey "param" }
41 | 'local' { TKey "local" }
42 | 'result' { TKey "result" }
43 | 'class' { TKey "class" }
44 | 'block' { TKey "block" }
45 |
46 | 'loop' { TKey "loop" }
47 | 'return' { TKey "return" }
48 | 'call' { TKey "call" }
49 | 'call_import' { TKey "call_impport" }
50 | 'call_indirect' { TKey "call_indirect" }
51 | 'if_else' { TKey "if_else" }
52 | 'if' { TKey "if" }
53 | 'br' { TKey "br" }
54 | 'br_if' { TKey "br_if" }
55 | 'tableswitch' { TKey "tableswitch" }
56 | 'case' { TKey "case" }
57 |
58 | 'get_local' { TKey "get_local" }
59 | 'set_local' { TKey "set_local" }
60 |
61 | 'add' { TKey "add" }
62 | 'mul' { TKey "mul" }
63 | 'sub' { TKey "sub" }
64 | 'div' { TKey "div" }
65 | 'abs' { TKey "abs" }
66 | 'eq' { TKey "eq" }
67 | 'min' { TKey "min" }
68 | 'max' { TKey "max" }
69 | 'ceil' { TKey "ceil" }
70 | 'trunc' { TKey "trunc" }
71 | 'floor' { TKey "floor" }
72 | 'neg' { TKey "neg" }
73 | 'sqrt' { TKey "sqrt" }
74 | 'nearest' { TKey "nearest" }
75 | 'copysign' { TKey "copysign" }
76 |
77 | 'nop' { TKey "nop" }
78 | 'unreachable' { TKey "unreachable" }
79 |
80 |
81 | %left 'and' 'or' 'xor'
82 | %left '<' '>' '<=' '>=' '=' '/='
83 | %left '+' '-'
84 | %left '*' '/' '//'
85 |
86 | %%
87 |
88 | -- Syntax
89 |
90 | prog :: { [Decl] }
91 | : list(top) { $1 }
92 |
93 | name :: { Name }
94 | : ident { Name (T.pack $1) }
95 | | integer { UnName (fromIntegral $1) }
96 |
97 | top :: { Decl }
98 | : mod { ModDecl $1 }
99 | | sexp { ExprDecl $1 }
100 |
101 | mod :: { Module }
102 | : '(' 'module' list(func) ')' { Module $3 }
103 |
104 | typ :: { Type }
105 | : 'i32' { I32 }
106 | | 'i64' { I64 }
107 | | 'f32' { F32 }
108 | | 'f64' { F64 }
109 |
110 | param :: { Param }
111 | : '(' 'param' name typ ')' { Param (Just $3) $4 }
112 | | '(' 'param' typ ')' { Param Nothing $3 }
113 | | '(' 'result' typ ')' { Result $3 }
114 | | sexp { Body $1 }
115 |
116 | func :: { Func }
117 | : '(' 'func' name list1(param) ')'
118 | { Func (Just $3) $4 [] }
119 |
120 | | '(' 'func' list1(param) ')'
121 | { Func Nothing $3 [] }
122 |
123 | | '(' 'export' str value ')' { Export $3 $4 }
124 |
125 | sexp :: { Expr }
126 | : '(' expr ')' { $2 }
127 | | value { Lit $1 }
128 |
129 | value :: { Value }
130 | : real { VF32 (undefined $1) }
131 | | integer { VI32 (fromInteger $1) }
132 |
133 | binop :: { BinOp }
134 | : 'mul' { Mul }
135 | | 'add' { Add }
136 | | 'sub' { Sub }
137 | | 'div' { Div }
138 | | 'min' { Min }
139 | | 'max' { Max }
140 | | 'copysign' { CopySign }
141 |
142 | unop :: { UnOp }
143 | : 'neg' { Neg }
144 | | 'abs' { Abs }
145 | | 'ceil' { Ceil }
146 | | 'floor' { Floor }
147 | | 'trunc' { Trunc }
148 | | 'nearest' { Nearest }
149 | | 'sqrt' { Sqrt }
150 |
151 | relop :: { RelOp }
152 | : 'eq' { Eq }
153 |
154 | expr :: { Expr }
155 | : 'nop' { Nop }
156 | | 'unreachable' { Unreachable }
157 | | 'block' list(sexp) { Block Nothing $2 }
158 | | 'block' name list(sexp) { Block (Just $2) $3 }
159 | | 'if' sexp sexp { If $2 $3 }
160 | | 'if_else' sexp sexp sexp { IfElse $2 $3 $4 }
161 | | 'br_if' sexp name sexp { BrIf $2 $3 $4 }
162 |
163 | | 'loop' name name list(sexp) { Loop (Just $2) (Just $3) $4 }
164 | | 'loop' name list(sexp) { Loop (Just $2) Nothing $3 }
165 | | 'loop' list(sexp) { Loop Nothing Nothing $2 }
166 |
167 | | 'br' name sexp { Br $2 (Just $3) }
168 | | 'br' name { Br $2 Nothing }
169 | | 'return' sexp { Return $2 }
170 | | 'call' name list(sexp) { Call $2 $3 }
171 | | 'get_local' name { GetLocal $2 }
172 | | 'set_local' name sexp { SetLocal $2 $3 }
173 |
174 | -- | 'i32' '.' 'const' value { Const I32 $4 }
175 | -- | 'i64' '.' 'const' value { Const I64 $4 }
176 | -- | 'f32' '.' 'const' value { Const F32 $4 }
177 | -- | 'f64' '.' 'const' value { Const F64 $4 }
178 |
179 | | typ '.' binop sexp sexp { Bin $3 $1 $4 $5 }
180 | | typ '.' unop sexp { Un $3 $1 $4 }
181 | | typ '.' 'const' value { Const $1 $4 }
182 | | typ '.' relop sexp sexp { Rel $3 $1 $4 $5 }
183 |
184 | -- Utils
185 |
186 | rev_list(p)
187 | : rev_list(p) p { $2 : $1 }
188 | | {- empty -} { [] }
189 |
190 | rev_list1(p)
191 | : rev_list1(p) p { $2 : $1 }
192 | | p { [$1] }
193 |
194 | -- List of zero or more p.
195 | list(p)
196 | : rev_list(p) { reverse $1 }
197 |
198 | -- A list of at least 1 p's
199 | list1(p) : rev_list1(p) { reverse $1 }
200 | {
201 |
202 | happyError :: ParseM a
203 | happyError = ParseM $ \(S _ toks) -> Left $ ParseError $ "happyError: " ++ show toks
204 |
205 | }
206 |
207 | -- vim: set filetype=happy:
208 |
--------------------------------------------------------------------------------
/src/Language/Wasm/Position.hs:
--------------------------------------------------------------------------------
1 | module Language.Wasm.Position where
2 |
3 | -------------------------------------------------------------------------------
4 | -- Data
5 | -------------------------------------------------------------------------------
6 |
7 | data Position = Position
8 | { line :: !Int
9 | , col :: !Int
10 | } deriving (Eq, Ord, Show)
11 |
12 | data Range = Range
13 | { from :: !Position
14 | , to :: !Position
15 | , source :: FilePath
16 | } deriving (Eq, Show)
17 |
18 | data Located a = Located { srcRange :: !Range, thing :: a }
19 | deriving (Eq, Show)
20 |
21 | emptyRange :: Range
22 | emptyRange = Range { from = start, to = start, source = "" }
23 |
24 | start :: Position
25 | start = Position { line = 1, col = 1 }
26 |
27 | move :: Position -> Char -> Position
28 | move p c = case c of
29 | '\t' -> p { col = ((col p + 7) `div` 8) * 8 + 1 }
30 | '\n' -> p { col = 1, line = 1 + line p }
31 | _ -> p { col = 1 + col p }
32 |
33 | rComb :: Range -> Range -> Range
34 | rComb r1 r2 = Range { from = rFrom, to = rTo, source = source r1 }
35 | where rFrom = min (from r1) (from r2)
36 | rTo = max (to r1) (to r2)
37 |
38 | rCombs :: [Range] -> Range
39 | rCombs = foldl1 rComb
40 |
41 | -------------------------------------------------------------------------------
42 | -- Types
43 | -------------------------------------------------------------------------------
44 |
45 | instance Functor Located where
46 | fmap f l = l { thing = f (thing l) }
47 |
48 | class HasLoc t where
49 | getLoc :: t -> Maybe Range
50 |
51 | instance HasLoc Range where
52 | getLoc = Just
53 |
54 | instance HasLoc (Located a) where
55 | getLoc r = Just (srcRange r)
56 |
57 | instance (HasLoc a, HasLoc b) => HasLoc (a, b) where
58 | getLoc (x, y) =
59 | case getLoc x of
60 | Nothing -> getLoc y
61 | Just l1 ->
62 | case getLoc y of
63 | Nothing -> return l1
64 | Just l2 -> return (rComb l1 l2)
65 |
66 | instance HasLoc a => HasLoc [a] where
67 | getLoc = go Nothing
68 | where
69 | go x [] = x
70 | go Nothing (x:xs) = go (getLoc x) xs
71 | go (Just l) (x:xs) = case getLoc x of
72 | Nothing -> go (Just l) xs
73 | Just l1 -> go (Just (rComb l l1)) xs
74 |
75 | class HasLoc t => AddLoc t where
76 | addLoc :: t -> Range -> t
77 | dropLoc :: t -> t
78 |
79 | instance AddLoc (Located a) where
80 | addLoc t r = t { srcRange = r }
81 | dropLoc r = r
82 |
83 | at :: (HasLoc l, AddLoc t) => l -> t -> t
84 | at l e = maybe e (addLoc e) (getLoc l)
85 |
--------------------------------------------------------------------------------
/src/Language/Wasm/Pretty.hs:
--------------------------------------------------------------------------------
1 | -- | Pretty printer for Textual AST.
2 |
3 | {-# LANGUAGE FlexibleInstances #-}
4 |
5 | module Language.Wasm.Pretty (
6 | pretty,
7 | display,
8 | ) where
9 |
10 | import Prelude hiding ((<$>))
11 |
12 | import Language.Wasm.Syntax
13 | import qualified Data.Text as T
14 | import Text.PrettyPrint.ANSI.Leijen
15 |
16 | instance Pretty Name where
17 | pretty (Name t) = text (T.unpack t)
18 | pretty (UnName n) = pretty (fromIntegral n :: Int)
19 |
20 | instance Pretty Expr where
21 | prettyList = nest 4 . vsep . map (parens . pretty)
22 | pretty expr = case expr of
23 | Nop -> text "nop"
24 | Unreachable -> text "unreachable"
25 | Block name e -> text "block" <+> maybe empty pretty name <$> pretty e
26 | If cond true -> text "if" <+> pretty [cond,true]
27 | IfElse cond true false -> text "if_else" <+> pretty [cond,true,false]
28 | BrIf cond name e -> text "todo"
29 | Loop{} -> text "todo"
30 | Br name e -> pretty [text "br" <+> pretty name]
31 | Return e -> text "return" <+> parens (pretty e)
32 | Call name _ -> text "todo"
33 | Const typ value -> pretty typ <> dot <> text "const" <+> pretty value
34 | Lit value -> pretty value
35 | Load memop e -> text "todo"
36 | Store memop e -> text "todo"
37 | GetLocal name -> text "get_local" <+> pretty name
38 | SetLocal name e -> text "set_local" <+> pretty name <+> parens (pretty e)
39 | LoadExtend extop e -> text "todo"
40 | StoreWrap wrapop e1 e2 -> text "todo"
41 | Bin binop typ e1 e2 -> pretty typ <> dot <> pretty binop <+> parens (pretty e1) <+> parens( pretty e2)
42 | Un unop typ e -> pretty typ <> dot <> pretty unop <+> parens (pretty e)
43 | Rel relop typ e1 e2 -> pretty typ <> dot <> pretty relop <+> parens (pretty e1) <+> parens( pretty e2)
44 | Sel selop e1 e2 e3 -> text "todo"
45 | Convert cvtop ty e -> text "todo"
46 | Host hostop _ -> text "todo"
47 |
48 | instance Pretty BinOp where
49 | pretty binop = text $ case binop of
50 | Add -> "add"
51 | Sub -> "sub"
52 | Mul -> "mul"
53 | DivS -> "divs"
54 | DivU -> "divu"
55 | RemS -> "rems"
56 | RemU -> "remu"
57 | And -> "and"
58 | Or -> "or"
59 | Xor -> "xor"
60 | Shl -> "shl"
61 | ShrU -> "shr_u"
62 | ShrS -> "shr_s"
63 | RotL -> "rotl"
64 | RotR -> "Rotr"
65 | Div -> "div"
66 | CopySign -> "copysign"
67 | Min -> "min"
68 | Max -> "max"
69 |
70 | instance Pretty UnOp where
71 | pretty unop = text $ case unop of
72 | Clz -> "clz"
73 | Ctz -> "ctz"
74 | Popcnt -> "popcnt"
75 | Neg -> "neg"
76 | Abs -> "abs"
77 | Ceil -> "ceil"
78 | Floor -> "floor"
79 | Trunc -> "trunc"
80 | Nearest -> "nearest"
81 | Sqrt -> "sqrt"
82 |
83 | instance Pretty RelOp where
84 | pretty relop = text $ case relop of
85 | Eqz -> "eqz"
86 | Eq -> "eq"
87 | Ne -> "ne"
88 | LtS -> "lts"
89 | LtU -> "ltu"
90 | LeS -> "les"
91 | LeU -> "leu"
92 | GtS -> "gts"
93 | GtU -> "gtu"
94 | GeS -> "ges"
95 | GeU -> "geu"
96 | Lt -> "lt"
97 | Le -> "le"
98 | Gt -> "gt"
99 | Ge -> "ge"
100 |
101 | instance Pretty Value where
102 | pretty value = text $ case value of
103 | VI32 v -> show v
104 | VI64 v -> show v
105 | VF32 v -> show v
106 | VF64 v -> show v
107 |
108 | instance Pretty Func where
109 | prettyList = vsep . map (parens . pretty)
110 | pretty f = case f of
111 | Export name value -> text "export" <+> pretty name <+> pretty value
112 | Import name value -> text "Import" <+> pretty name <+> pretty value
113 | Func name params body -> nest 4 (text "func" <+> maybe empty pretty name <+> pretty params <$> pretty body )
114 |
115 | instance Pretty Decl where
116 | pretty d = case d of
117 | ModDecl m -> pretty m
118 | ExprDecl expr -> pretty expr
119 |
120 | instance Pretty Module where
121 | pretty Module { _funcs=funcs } = parens (nest 4 (text "module" <$> pretty funcs))
122 |
123 | instance Pretty Param where
124 | prettyList = fillSep . map (parens . pretty)
125 | pretty param = case param of
126 | Param (Just name) typ -> text "param" <+> pretty name <+> pretty typ
127 | Param Nothing typ -> text "param" <+> pretty typ
128 | Result typ -> text "result" <+> pretty typ
129 | Body expr -> pretty expr
130 |
131 | instance Pretty Type where
132 | pretty ty = text $ case ty of
133 | I32 -> "i32"
134 | I64 -> "i64"
135 | F32 -> "f32"
136 | F64 -> "f64"
137 | FuncType -> "func"
138 |
139 | display :: Pretty a => a -> String
140 | display x = displayS (renderPretty 0.4 180 (pretty x)) ""
141 |
--------------------------------------------------------------------------------
/src/Language/Wasm/Syntax.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE GeneralizedNewtypeDeriving #-}
2 |
3 | module Language.Wasm.Syntax (
4 | Name(..),
5 | Expr(..),
6 | Decl(..),
7 | Func(..),
8 | Type(..),
9 | Value(..),
10 | Param(..),
11 | Module(..),
12 | UnOp(..),
13 | BinOp(..),
14 | RelOp(..),
15 | ConvertOp(..),
16 |
17 | U32,
18 | F32,
19 | F64,
20 | I32,
21 | I64,
22 | ) where
23 |
24 | import Data.Int
25 | import Data.Word
26 | import Data.String
27 | import qualified Data.Text as T
28 |
29 | type U32 = Word32
30 | type F32 = Float
31 | type F64 = Double
32 | type I32 = Int32
33 | type I64 = Int64
34 |
35 | data Name
36 | = Name T.Text
37 | | UnName Word32
38 | deriving (Eq, Ord, Show)
39 |
40 | instance IsString Name where
41 | fromString = Name . T.pack
42 |
43 | data Expr
44 | = Nop
45 | | Unreachable
46 | | Block (Maybe Name) [Expr]
47 | | If Expr Expr
48 | | IfElse Expr Expr Expr
49 | | BrIf Expr Name Expr
50 | | Loop (Maybe Name) (Maybe Name) [Expr]
51 | | Br Name (Maybe Expr)
52 | | Return Expr
53 | | Call Name [Expr]
54 | | Const Type Value
55 | | Lit Value
56 | | Load Memop Expr
57 | | Store Memop Expr
58 | | GetLocal Name
59 | | SetLocal Name Expr
60 | | LoadExtend Extop Expr
61 | | StoreWrap Wrapop Expr Expr
62 | | Bin BinOp Type Expr Expr
63 | | Un UnOp Type Expr
64 | | Rel RelOp Type Expr Expr
65 | | Sel SelOp Expr Expr Expr
66 | | Convert ConvertOp Type Expr
67 | | Host Hostop [Expr]
68 | deriving (Eq, Show)
69 |
70 | data UnOp
71 | -- Integer
72 | = Clz
73 | | Ctz
74 | | Popcnt
75 |
76 | -- Floating Point
77 | | Neg
78 | | Abs
79 | | Ceil
80 | | Floor
81 | | Trunc
82 | | Nearest
83 | | Sqrt
84 | deriving (Eq, Show)
85 |
86 | data BinOp
87 | = Add
88 | | Sub
89 | | Mul
90 | | DivS
91 | | DivU
92 | | RemS
93 | | RemU
94 | | And
95 | | Or
96 | | Xor
97 | | Shl
98 | | ShrU
99 | | ShrS
100 | | RotR
101 | | RotL
102 | | Div
103 | | CopySign
104 | | Min
105 | | Max
106 | deriving (Eq, Show)
107 |
108 | data SelOp
109 | = Select
110 | deriving (Eq, Show)
111 |
112 | data RelOp
113 | = Eqz
114 | | Eq
115 | | Ne
116 | | LtS
117 | | LtU
118 | | GtS
119 | | GtU
120 | | LeS
121 | | LeU
122 | | GeS
123 | | GeU
124 | | Lt
125 | | Gt
126 | | Le
127 | | Ge
128 | deriving (Eq, Show)
129 |
130 | data ConvertOp
131 | = WrapI64
132 | | TruncSF32
133 | | TruncUF32
134 | | TruncSF64
135 | | TruncUF64
136 | | ExtendSI32
137 | | ExtendUI32
138 | | ConvertSI32
139 | | ConvertUI32
140 | | ConvertSI64
141 | | ConvertUI64
142 | | DemoteF64
143 | | PromoteF32
144 |
145 | | ReinterpretF32
146 | | ReinterpretF64
147 | | ReinterpretI32
148 | | ReinterpretI64
149 | deriving (Eq, Show)
150 |
151 | data Extop
152 | = Extop Memop MemSize Extension
153 | deriving (Eq, Show)
154 |
155 | data Wrapop
156 | = Wrapop Memop MemSize
157 | deriving (Eq, Show)
158 |
159 | type Address = Int64
160 | type Size = Int64
161 | type Offset = Address
162 |
163 | data MemSize
164 | = Mem8
165 | | Mem16
166 | | Mem32
167 | deriving (Eq, Show)
168 |
169 | data Extension
170 | = SX
171 | | ZX
172 | deriving (Eq, Show)
173 |
174 | data Memop = Memop
175 | { ty :: Value
176 | , offset :: Offset
177 | , align :: Maybe Int
178 | } deriving (Eq, Show)
179 |
180 | data Hostop
181 | = MemorySize
182 | | GrowMemory
183 | | HasFeature Name
184 | deriving (Eq, Show)
185 |
186 | data Value
187 | = VI32 Int32
188 | | VI64 Int64
189 | | VF32 Float
190 | | VF64 Double
191 | deriving (Eq, Show)
192 |
193 | data Decl
194 | = ModDecl Module
195 | | ExprDecl Expr
196 | deriving (Eq, Show)
197 |
198 | data Func = Func
199 | { _ftype :: Maybe Name
200 | , _params :: [Param]
201 | , _body :: [Expr]
202 | }
203 | | Export String Value
204 | | Import Name Int
205 | deriving (Eq, Show)
206 |
207 | data Module = Module
208 | { _funcs :: [Func]
209 | } deriving (Eq, Show)
210 |
211 | data Param
212 | = Param (Maybe Name) Type
213 | | Result Type
214 | | Body Expr
215 | deriving (Eq, Show)
216 |
217 | data Type
218 | = I32
219 | | I64
220 | | F32
221 | | F64
222 | | FuncType
223 | deriving (Eq, Show)
224 |
--------------------------------------------------------------------------------
/stack.yaml:
--------------------------------------------------------------------------------
1 | resolver: lts-10.0
2 | packages:
3 | - '.'
4 | extra-deps:
5 | - repline-0.1.4.0
6 | - io-capture-0.3
7 | flags: {}
8 | extra-package-dbs: []
9 |
--------------------------------------------------------------------------------
/test.js:
--------------------------------------------------------------------------------
1 | buffer = readbuffer('example1.bin');
2 | module = WASM.instantiateModule(buffer, {});
3 | module.test();
4 |
--------------------------------------------------------------------------------
/test.sh:
--------------------------------------------------------------------------------
1 | x64.debug/d8 --expose-wasm --trace_wasm_decoder --trace_wasm_compiiler < test.js
2 |
--------------------------------------------------------------------------------
/tests/Test.hs:
--------------------------------------------------------------------------------
1 | module Main (
2 | main
3 | ) where
4 |
5 | import Control.Monad.Trans
6 | import Data.Either
7 | import Data.Serialize
8 |
9 | import Language.Wasm.Core
10 | import Language.Wasm.Binary
11 | import Language.Wasm.Pretty
12 | import Language.Wasm.Entry (parse)
13 |
14 | import System.FilePath
15 | import System.FilePath.Posix
16 |
17 | import Test.Tasty
18 | import Test.Tasty.HUnit
19 | import Test.Tasty.Golden
20 |
21 | import qualified Hexdump
22 | import qualified Data.Text.Lazy.IO as T
23 | import qualified Data.ByteString as BS
24 |
25 | testFiles :: MonadIO m => m [FilePath]
26 | testFiles = liftIO $ findByExtension [".wast"] "tests/spec/input"
27 |
28 | parser :: [(FilePath, String)] -> TestTree
29 | parser inputs = testGroup "Parser does not fail on syntactically correct inputs" testCases
30 | where
31 | testCases = [ testCase (takeBaseName name) (assertion contents) | (name, contents) <- inputs ]
32 | assertion contents = let result = parse contents
33 | in assertBool (show result) (isRight result)
34 | prettyPrinter :: TestTree
35 | prettyPrinter = testGroup "Pretty Printer" []
36 |
37 | binaryWriter :: [(FilePath, String)] -> TestTree
38 | binaryWriter inputs = testGroup "Binary Writer" $ do
39 | (path, contents) <- inputs
40 | let
41 | outf = "tests/spec/output" > replaceExtension (takeFileName path) "wasm"
42 | astf = "tests/spec/output" > replaceExtension (takeFileName path) "ast"
43 | goldenf = "tests/spec/golden" > replaceExtension (takeFileName path) "wasm"
44 | action = do
45 | let ast = (parse contents)
46 | case ast of
47 | Left err -> return ()
48 | Right [mod] -> do
49 | let bs = encode (toCore mod)
50 | writeFile astf (display mod)
51 | writeFile outf (Hexdump.prettyHex bs)
52 | return $ goldenVsFile (takeBaseName path) goldenf outf action
53 |
54 | main :: IO ()
55 | main = do
56 | paths <- testFiles
57 | contents <- mapM readFile paths
58 | let files = (zip paths contents)
59 | defaultMain $ testGroup "Test Suite" [ parser files, prettyPrinter, binaryWriter files]
60 |
--------------------------------------------------------------------------------
/tests/failing/address.wast:
--------------------------------------------------------------------------------
1 | (module
2 | (memory 1)
3 | (data (i32.const 0) "abcdefghijklmnopqrstuvwxyz")
4 |
5 | (func (export "good1") (param $i i32) (result i32)
6 | (i32.load8_u offset=0 (get_local $i)) ;; 97 'a'
7 | )
8 | (func (export "good2") (param $i i32) (result i32)
9 | (i32.load8_u offset=1 (get_local $i)) ;; 98 'b'
10 | )
11 | (func (export "good3") (param $i i32) (result i32)
12 | (i32.load8_u offset=2 (get_local $i)) ;; 99 'c'
13 | )
14 | (func (export "good4") (param $i i32) (result i32)
15 | (i32.load8_u offset=25 (get_local $i)) ;; 122 'z'
16 | )
17 |
18 | (func (export "good5") (param $i i32) (result i32)
19 | (i32.load16_u offset=0 (get_local $i)) ;; 25185 'ab'
20 | )
21 | (func (export "good6") (param $i i32) (result i32)
22 | (i32.load16_u align=1 (get_local $i)) ;; 25185 'ab'
23 | )
24 | (func (export "good7") (param $i i32) (result i32)
25 | (i32.load16_u offset=1 align=1 (get_local $i)) ;; 25442 'bc'
26 | )
27 | (func (export "good8") (param $i i32) (result i32)
28 | (i32.load16_u offset=2 (get_local $i)) ;; 25699 'cd'
29 | )
30 | (func (export "good9") (param $i i32) (result i32)
31 | (i32.load16_u offset=25 align=1 (get_local $i)) ;; 122 'z\0'
32 | )
33 |
34 | (func (export "good10") (param $i i32) (result i32)
35 | (i32.load offset=0 (get_local $i)) ;; 1684234849 'abcd'
36 | )
37 | (func (export "good11") (param $i i32) (result i32)
38 | (i32.load offset=1 align=1 (get_local $i)) ;; 1701077858 'bcde'
39 | )
40 | (func (export "good12") (param $i i32) (result i32)
41 | (i32.load offset=2 align=2 (get_local $i)) ;; 1717920867 'cdef'
42 | )
43 | (func (export "good13") (param $i i32) (result i32)
44 | (i32.load offset=25 align=1 (get_local $i)) ;; 122 'z\0\0\0'
45 | )
46 |
47 | (func (export "bad") (param $i i32)
48 | (drop (i32.load offset=4294967295 (get_local $i)))
49 | )
50 | )
51 |
52 | (assert_return (invoke "good1" (i32.const 0)) (i32.const 97))
53 | (assert_return (invoke "good2" (i32.const 0)) (i32.const 98))
54 | (assert_return (invoke "good3" (i32.const 0)) (i32.const 99))
55 | (assert_return (invoke "good4" (i32.const 0)) (i32.const 122))
56 | (assert_return (invoke "good5" (i32.const 0)) (i32.const 25185))
57 | (assert_return (invoke "good6" (i32.const 0)) (i32.const 25185))
58 | (assert_return (invoke "good7" (i32.const 0)) (i32.const 25442))
59 | (assert_return (invoke "good8" (i32.const 0)) (i32.const 25699))
60 | (assert_return (invoke "good9" (i32.const 0)) (i32.const 122))
61 | (assert_return (invoke "good10" (i32.const 0)) (i32.const 1684234849))
62 | (assert_return (invoke "good11" (i32.const 0)) (i32.const 1701077858))
63 | (assert_return (invoke "good12" (i32.const 0)) (i32.const 1717920867))
64 | (assert_return (invoke "good13" (i32.const 0)) (i32.const 122))
65 |
66 | (assert_return (invoke "good1" (i32.const 65507)) (i32.const 0))
67 | (assert_return (invoke "good2" (i32.const 65507)) (i32.const 0))
68 | (assert_return (invoke "good3" (i32.const 65507)) (i32.const 0))
69 | (assert_return (invoke "good4" (i32.const 65507)) (i32.const 0))
70 | (assert_return (invoke "good5" (i32.const 65507)) (i32.const 0))
71 | (assert_return (invoke "good6" (i32.const 65507)) (i32.const 0))
72 | (assert_return (invoke "good7" (i32.const 65507)) (i32.const 0))
73 | (assert_return (invoke "good8" (i32.const 65507)) (i32.const 0))
74 | (assert_return (invoke "good9" (i32.const 65507)) (i32.const 0))
75 | (assert_return (invoke "good10" (i32.const 65507)) (i32.const 0))
76 | (assert_return (invoke "good11" (i32.const 65507)) (i32.const 0))
77 | (assert_return (invoke "good12" (i32.const 65507)) (i32.const 0))
78 | (assert_return (invoke "good13" (i32.const 65507)) (i32.const 0))
79 |
80 | (assert_return (invoke "good1" (i32.const 65508)) (i32.const 0))
81 | (assert_return (invoke "good2" (i32.const 65508)) (i32.const 0))
82 | (assert_return (invoke "good3" (i32.const 65508)) (i32.const 0))
83 | (assert_return (invoke "good4" (i32.const 65508)) (i32.const 0))
84 | (assert_return (invoke "good5" (i32.const 65508)) (i32.const 0))
85 | (assert_return (invoke "good6" (i32.const 65508)) (i32.const 0))
86 | (assert_return (invoke "good7" (i32.const 65508)) (i32.const 0))
87 | (assert_return (invoke "good8" (i32.const 65508)) (i32.const 0))
88 | (assert_return (invoke "good9" (i32.const 65508)) (i32.const 0))
89 | (assert_return (invoke "good10" (i32.const 65508)) (i32.const 0))
90 | (assert_return (invoke "good11" (i32.const 65508)) (i32.const 0))
91 | (assert_return (invoke "good12" (i32.const 65508)) (i32.const 0))
92 | (assert_trap (invoke "good13" (i32.const 65508)) "out of bounds memory access")
93 |
94 | (assert_trap (invoke "bad" (i32.const 0)) "out of bounds memory access")
95 | (assert_trap (invoke "bad" (i32.const 1)) "out of bounds memory access")
96 |
97 | (assert_malformed
98 | (module quote
99 | "(memory 1)"
100 | "(func (drop (i32.load offset=4294967296 (i32.const 0))))"
101 | )
102 | "i32 constant"
103 | )
104 |
--------------------------------------------------------------------------------
/tests/failing/align.wast:
--------------------------------------------------------------------------------
1 | (assert_malformed
2 | (module quote
3 | "(module (memory 0) (func (drop (i64.load align=0 (i32.const 0)))))"
4 | )
5 | "alignment"
6 | )
7 | (assert_malformed
8 | (module quote
9 | "(module (memory 0) (func (drop (i64.load align=7 (i32.const 0)))))"
10 | )
11 | "alignment"
12 | )
13 | (assert_invalid
14 | (module (memory 0) (func (drop (i64.load align=16 (i32.const 0)))))
15 | "alignment"
16 | )
17 |
18 | (assert_malformed
19 | (module quote
20 | "(module (memory 0) (func (i64.store align=0 (i32.const 0) (i64.const 0))))"
21 | )
22 | "alignment"
23 | )
24 | (assert_malformed
25 | (module quote
26 | "(module (memory 0) (func (i64.store align=5 (i32.const 0) (i64.const 0))))"
27 | )
28 | "alignment"
29 | )
30 | (assert_invalid
31 | (module (memory 0) (func (i64.store align=16 (i32.const 0) (i64.const 0))))
32 | "alignment"
33 | )
34 |
--------------------------------------------------------------------------------
/tests/failing/binary.wast:
--------------------------------------------------------------------------------
1 | (module binary "\00asm\01\00\00\00")
2 | (module binary "\00asm" "\01\00\00\00")
3 | (module $M1 binary "\00asm\01\00\00\00")
4 | (module $M2 binary "\00asm" "\01\00\00\00")
5 |
6 | (assert_malformed (module binary "") "unexpected end")
7 | (assert_malformed (module binary "\01") "unexpected end")
8 | (assert_malformed (module binary "\00as") "unexpected end")
9 | (assert_malformed (module binary "asm\00") "magic header not detected")
10 | (assert_malformed (module binary "msa\00") "magic header not detected")
11 | (assert_malformed (module binary "msa\00\01\00\00\00") "magic header not detected")
12 | (assert_malformed (module binary "msa\00\00\00\00\01") "magic header not detected")
13 | (assert_malformed (module binary "asm\01\00\00\00\00") "magic header not detected")
14 | (assert_malformed (module binary "wasm\01\00\00\00") "magic header not detected")
15 | (assert_malformed (module binary "\7fasm\01\00\00\00") "magic header not detected")
16 | (assert_malformed (module binary "\80asm\01\00\00\00") "magic header not detected")
17 | (assert_malformed (module binary "\82asm\01\00\00\00") "magic header not detected")
18 | (assert_malformed (module binary "\ffasm\01\00\00\00") "magic header not detected")
19 |
20 | ;; 8-byte endian-reversed.
21 | (assert_malformed (module binary "\00\00\00\01msa\00") "magic header not detected")
22 |
23 | ;; Middle-endian byte orderings.
24 | (assert_malformed (module binary "a\00ms\00\01\00\00") "magic header not detected")
25 | (assert_malformed (module binary "sm\00a\00\00\01\00") "magic header not detected")
26 |
27 | ;; Upper-cased.
28 | (assert_malformed (module binary "\00ASM\01\00\00\00") "magic header not detected")
29 |
30 | ;; EBCDIC-encoded magic.
31 | (assert_malformed (module binary "\00\81\a2\94\01\00\00\00") "magic header not detected")
32 |
33 | ;; Leading UTF-8 BOM.
34 | (assert_malformed (module binary "\ef\bb\bf\00asm\01\00\00\00") "magic header not detected")
35 |
36 | (assert_malformed (module binary "\00asm") "unexpected end")
37 | (assert_malformed (module binary "\00asm\01") "unexpected end")
38 | (assert_malformed (module binary "\00asm\01\00\00") "unexpected end")
39 | (assert_malformed (module binary "\00asm\00\00\00\00") "unknown binary version")
40 | (assert_malformed (module binary "\00asm\0d\00\00\00") "unknown binary version")
41 | (assert_malformed (module binary "\00asm\0e\00\00\00") "unknown binary version")
42 | (assert_malformed (module binary "\00asm\00\01\00\00") "unknown binary version")
43 | (assert_malformed (module binary "\00asm\00\00\01\00") "unknown binary version")
44 | (assert_malformed (module binary "\00asm\00\00\00\01") "unknown binary version")
45 |
--------------------------------------------------------------------------------
/tests/failing/block.wast:
--------------------------------------------------------------------------------
1 | ;; Test `block` operator
2 |
3 | (module
4 | ;; Auxiliary definition
5 | (func $dummy)
6 |
7 | (func (export "empty")
8 | (block)
9 | (block $l)
10 | )
11 |
12 | (func (export "singular") (result i32)
13 | (block (nop))
14 | (block (result i32) (i32.const 7))
15 | )
16 |
17 | (func (export "multi") (result i32)
18 | (block (call $dummy) (call $dummy) (call $dummy) (call $dummy))
19 | (block (result i32) (call $dummy) (call $dummy) (call $dummy) (i32.const 8))
20 | )
21 |
22 | (func (export "nested") (result i32)
23 | (block (result i32)
24 | (block (call $dummy) (block) (nop))
25 | (block (result i32) (call $dummy) (i32.const 9))
26 | )
27 | )
28 |
29 | (func (export "deep") (result i32)
30 | (block (result i32) (block (result i32)
31 | (block (result i32) (block (result i32)
32 | (block (result i32) (block (result i32)
33 | (block (result i32) (block (result i32)
34 | (block (result i32) (block (result i32)
35 | (block (result i32) (block (result i32)
36 | (block (result i32) (block (result i32)
37 | (block (result i32) (block (result i32)
38 | (block (result i32) (block (result i32)
39 | (block (result i32) (block (result i32)
40 | (block (result i32) (block (result i32)
41 | (block (result i32) (block (result i32)
42 | (block (result i32) (block (result i32)
43 | (block (result i32) (block (result i32)
44 | (block (result i32) (block (result i32)
45 | (block (result i32) (block (result i32)
46 | (block (result i32) (block (result i32)
47 | (block (result i32) (block (result i32)
48 | (block (result i32) (block (result i32)
49 | (call $dummy) (i32.const 150)
50 | ))
51 | ))
52 | ))
53 | ))
54 | ))
55 | ))
56 | ))
57 | ))
58 | ))
59 | ))
60 | ))
61 | ))
62 | ))
63 | ))
64 | ))
65 | ))
66 | ))
67 | ))
68 | ))
69 | )
70 |
71 | (func (export "as-unary-operand") (result i32)
72 | (i32.ctz (block (result i32) (call $dummy) (i32.const 13)))
73 | )
74 | (func (export "as-binary-operand") (result i32)
75 | (i32.mul
76 | (block (result i32) (call $dummy) (i32.const 3))
77 | (block (result i32) (call $dummy) (i32.const 4))
78 | )
79 | )
80 | (func (export "as-test-operand") (result i32)
81 | (i32.eqz (block (result i32) (call $dummy) (i32.const 13)))
82 | )
83 | (func (export "as-compare-operand") (result i32)
84 | (f32.gt
85 | (block (result f32) (call $dummy) (f32.const 3))
86 | (block (result f32) (call $dummy) (f32.const 3))
87 | )
88 | )
89 |
90 | (func (export "break-bare") (result i32)
91 | (block (br 0) (unreachable))
92 | (block (br_if 0 (i32.const 1)) (unreachable))
93 | (block (br_table 0 (i32.const 0)) (unreachable))
94 | (block (br_table 0 0 0 (i32.const 1)) (unreachable))
95 | (i32.const 19)
96 | )
97 | (func (export "break-value") (result i32)
98 | (block (result i32) (br 0 (i32.const 18)) (i32.const 19))
99 | )
100 | (func (export "break-repeated") (result i32)
101 | (block (result i32)
102 | (br 0 (i32.const 18))
103 | (br 0 (i32.const 19))
104 | (drop (br_if 0 (i32.const 20) (i32.const 0)))
105 | (drop (br_if 0 (i32.const 20) (i32.const 1)))
106 | (br 0 (i32.const 21))
107 | (br_table 0 (i32.const 22) (i32.const 4))
108 | (br_table 0 0 0 (i32.const 23) (i32.const 1))
109 | (i32.const 21)
110 | )
111 | )
112 | (func (export "break-inner") (result i32)
113 | (local i32)
114 | (set_local 0 (i32.const 0))
115 | (set_local 0 (i32.add (get_local 0) (block (result i32) (block (result i32) (br 1 (i32.const 0x1))))))
116 | (set_local 0 (i32.add (get_local 0) (block (result i32) (block (br 0)) (i32.const 0x2))))
117 | (set_local 0
118 | (i32.add (get_local 0) (block (result i32) (i32.ctz (br 0 (i32.const 0x4)))))
119 | )
120 | (set_local 0
121 | (i32.add (get_local 0) (block (result i32) (i32.ctz (block (result i32) (br 1 (i32.const 0x8))))))
122 | )
123 | (get_local 0)
124 | )
125 |
126 | (func (export "effects") (result i32)
127 | (local i32)
128 | (block
129 | (set_local 0 (i32.const 1))
130 | (set_local 0 (i32.mul (get_local 0) (i32.const 3)))
131 | (set_local 0 (i32.sub (get_local 0) (i32.const 5)))
132 | (set_local 0 (i32.mul (get_local 0) (i32.const 7)))
133 | (br 0)
134 | (set_local 0 (i32.mul (get_local 0) (i32.const 100)))
135 | )
136 | (i32.eq (get_local 0) (i32.const -14))
137 | )
138 | )
139 |
140 | (assert_return (invoke "empty"))
141 | (assert_return (invoke "singular") (i32.const 7))
142 | (assert_return (invoke "multi") (i32.const 8))
143 | (assert_return (invoke "nested") (i32.const 9))
144 | (assert_return (invoke "deep") (i32.const 150))
145 |
146 | (assert_return (invoke "as-unary-operand") (i32.const 0))
147 | (assert_return (invoke "as-binary-operand") (i32.const 12))
148 | (assert_return (invoke "as-test-operand") (i32.const 0))
149 | (assert_return (invoke "as-compare-operand") (i32.const 0))
150 |
151 | (assert_return (invoke "break-bare") (i32.const 19))
152 | (assert_return (invoke "break-value") (i32.const 18))
153 | (assert_return (invoke "break-repeated") (i32.const 18))
154 | (assert_return (invoke "break-inner") (i32.const 0xf))
155 |
156 | (assert_return (invoke "effects") (i32.const 1))
157 |
158 | (assert_invalid
159 | (module (func $type-empty-i32 (result i32) (block)))
160 | "type mismatch"
161 | )
162 | (assert_invalid
163 | (module (func $type-empty-i64 (result i64) (block)))
164 | "type mismatch"
165 | )
166 | (assert_invalid
167 | (module (func $type-empty-f32 (result f32) (block)))
168 | "type mismatch"
169 | )
170 | (assert_invalid
171 | (module (func $type-empty-f64 (result f64) (block)))
172 | "type mismatch"
173 | )
174 |
175 | (assert_invalid
176 | (module (func $type-value-num-vs-void
177 | (block (i32.const 1))
178 | ))
179 | "type mismatch"
180 | )
181 | (assert_invalid
182 | (module (func $type-value-empty-vs-num (result i32)
183 | (block (result i32))
184 | ))
185 | "type mismatch"
186 | )
187 | (assert_invalid
188 | (module (func $type-value-void-vs-num (result i32)
189 | (block (result i32) (nop))
190 | ))
191 | "type mismatch"
192 | )
193 | (assert_invalid
194 | (module (func $type-value-num-vs-num (result i32)
195 | (block (result i32) (f32.const 0))
196 | ))
197 | "type mismatch"
198 | )
199 | (assert_invalid
200 | (module (func $type-value-unreached-select (result i32)
201 | (block (result i64) (select (unreachable) (unreachable) (unreachable)))
202 | ))
203 | "type mismatch"
204 | )
205 |
206 | (assert_invalid
207 | (module (func $type-break-last-void-vs-num (result i32)
208 | (block (result i32) (br 0))
209 | ))
210 | "type mismatch"
211 | )
212 | (assert_invalid
213 | (module (func $type-break-empty-vs-num (result i32)
214 | (block (result i32) (br 0) (i32.const 1))
215 | ))
216 | "type mismatch"
217 | )
218 |
219 | (assert_invalid
220 | (module (func $type-break-void-vs-num (result i32)
221 | (block (result i32) (br 0 (nop)) (i32.const 1))
222 | ))
223 | "type mismatch"
224 | )
225 | (assert_invalid
226 | (module (func $type-break-num-vs-num (result i32)
227 | (block (result i32) (br 0 (i64.const 1)) (i32.const 1))
228 | ))
229 | "type mismatch"
230 | )
231 | (assert_invalid
232 | (module (func $type-break-first-void-vs-num (result i32)
233 | (block (result i32) (br 0 (nop)) (br 0 (i32.const 1)))
234 | ))
235 | "type mismatch"
236 | )
237 | (assert_invalid
238 | (module (func $type-break-first-num-vs-num (result i32)
239 | (block (result i32) (br 0 (i64.const 1)) (br 0 (i32.const 1)))
240 | ))
241 | "type mismatch"
242 | )
243 |
244 | (assert_invalid
245 | (module (func $type-break-nested-num-vs-void
246 | (block (result i32) (block (result i32) (br 1 (i32.const 1))) (br 0))
247 | ))
248 | "type mismatch"
249 | )
250 | (assert_invalid
251 | (module (func $type-break-nested-empty-vs-num (result i32)
252 | (block (result i32) (block (br 1)) (br 0 (i32.const 1)))
253 | ))
254 | "type mismatch"
255 | )
256 |
257 | (assert_invalid
258 | (module (func $type-break-nested-void-vs-num (result i32)
259 | (block (result i32) (block (result i32) (br 1 (nop))) (br 0 (i32.const 1)))
260 | ))
261 | "type mismatch"
262 | )
263 | (assert_invalid
264 | (module (func $type-break-nested-num-vs-num (result i32)
265 | (block (result i32)
266 | (block (result i32) (br 1 (i64.const 1))) (br 0 (i32.const 1))
267 | )
268 | ))
269 | "type mismatch"
270 | )
271 |
272 | (assert_invalid
273 | (module (func $type-break-operand-empty-vs-num (result i32)
274 | (i32.ctz (block (br 0)))
275 | ))
276 | "type mismatch"
277 | )
278 | (assert_invalid
279 | (module (func $type-break-operand-void-vs-num (result i32)
280 | (i64.ctz (block (br 0 (nop))))
281 | ))
282 | "type mismatch"
283 | )
284 | (assert_invalid
285 | (module (func $type-break-operand-num-vs-num (result i32)
286 | (i64.ctz (block (br 0 (i64.const 9))))
287 | ))
288 | "type mismatch"
289 | )
290 |
291 |
292 | (assert_malformed
293 | (module quote "(func block end $l)")
294 | "mismatching label"
295 | )
296 | (assert_malformed
297 | (module quote "(func block $a end $l)")
298 | "mismatching label"
299 | )
300 |
--------------------------------------------------------------------------------
/tests/failing/break-drop.wast:
--------------------------------------------------------------------------------
1 | (module
2 | (func (export "br") (block (br 0)))
3 | (func (export "br_if") (block (br_if 0 (i32.const 1))))
4 | (func (export "br_table") (block (br_table 0 (i32.const 0))))
5 | )
6 |
7 | (assert_return (invoke "br"))
8 | (assert_return (invoke "br_if"))
9 | (assert_return (invoke "br_table"))
10 |
--------------------------------------------------------------------------------
/tests/failing/call.wast:
--------------------------------------------------------------------------------
1 | ;; Test `call` operator
2 |
3 | (module
4 | ;; Auxiliary definitions
5 | (func $const-i32 (result i32) (i32.const 0x132))
6 | (func $const-i64 (result i64) (i64.const 0x164))
7 | (func $const-f32 (result f32) (f32.const 0xf32))
8 | (func $const-f64 (result f64) (f64.const 0xf64))
9 |
10 | (func $id-i32 (param i32) (result i32) (get_local 0))
11 | (func $id-i64 (param i64) (result i64) (get_local 0))
12 | (func $id-f32 (param f32) (result f32) (get_local 0))
13 | (func $id-f64 (param f64) (result f64) (get_local 0))
14 |
15 | (func $f32-i32 (param f32 i32) (result i32) (get_local 1))
16 | (func $i32-i64 (param i32 i64) (result i64) (get_local 1))
17 | (func $f64-f32 (param f64 f32) (result f32) (get_local 1))
18 | (func $i64-f64 (param i64 f64) (result f64) (get_local 1))
19 |
20 | ;; Typing
21 |
22 | (func (export "type-i32") (result i32) (call $const-i32))
23 | (func (export "type-i64") (result i64) (call $const-i64))
24 | (func (export "type-f32") (result f32) (call $const-f32))
25 | (func (export "type-f64") (result f64) (call $const-f64))
26 |
27 | (func (export "type-first-i32") (result i32) (call $id-i32 (i32.const 32)))
28 | (func (export "type-first-i64") (result i64) (call $id-i64 (i64.const 64)))
29 | (func (export "type-first-f32") (result f32) (call $id-f32 (f32.const 1.32)))
30 | (func (export "type-first-f64") (result f64) (call $id-f64 (f64.const 1.64)))
31 |
32 | (func (export "type-second-i32") (result i32)
33 | (call $f32-i32 (f32.const 32.1) (i32.const 32))
34 | )
35 | (func (export "type-second-i64") (result i64)
36 | (call $i32-i64 (i32.const 32) (i64.const 64))
37 | )
38 | (func (export "type-second-f32") (result f32)
39 | (call $f64-f32 (f64.const 64) (f32.const 32))
40 | )
41 | (func (export "type-second-f64") (result f64)
42 | (call $i64-f64 (i64.const 64) (f64.const 64.1))
43 | )
44 |
45 | ;; Recursion
46 |
47 | (func $fac (export "fac") (param i64) (result i64)
48 | (if (result i64) (i64.eqz (get_local 0))
49 | (then (i64.const 1))
50 | (else
51 | (i64.mul
52 | (get_local 0)
53 | (call $fac (i64.sub (get_local 0) (i64.const 1)))
54 | )
55 | )
56 | )
57 | )
58 |
59 | (func $fac-acc (export "fac-acc") (param i64 i64) (result i64)
60 | (if (result i64) (i64.eqz (get_local 0))
61 | (then (get_local 1))
62 | (else
63 | (call $fac-acc
64 | (i64.sub (get_local 0) (i64.const 1))
65 | (i64.mul (get_local 0) (get_local 1))
66 | )
67 | )
68 | )
69 | )
70 |
71 | (func $fib (export "fib") (param i64) (result i64)
72 | (if (result i64) (i64.le_u (get_local 0) (i64.const 1))
73 | (then (i64.const 1))
74 | (else
75 | (i64.add
76 | (call $fib (i64.sub (get_local 0) (i64.const 2)))
77 | (call $fib (i64.sub (get_local 0) (i64.const 1)))
78 | )
79 | )
80 | )
81 | )
82 |
83 | (func $even (export "even") (param i64) (result i32)
84 | (if (result i32) (i64.eqz (get_local 0))
85 | (then (i32.const 44))
86 | (else (call $odd (i64.sub (get_local 0) (i64.const 1))))
87 | )
88 | )
89 | (func $odd (export "odd") (param i64) (result i32)
90 | (if (result i32) (i64.eqz (get_local 0))
91 | (then (i32.const 99))
92 | (else (call $even (i64.sub (get_local 0) (i64.const 1))))
93 | )
94 | )
95 |
96 | ;; Stack exhaustion
97 |
98 | ;; Implementations are required to have every call consume some abstract
99 | ;; resource towards exhausting some abstract finite limit, such that
100 | ;; infinitely recursive test cases reliably trap in finite time. This is
101 | ;; because otherwise applications could come to depend on it on those
102 | ;; implementations and be incompatible with implementations that don't do
103 | ;; it (or don't do it under the same circumstances).
104 |
105 | (func $runaway (export "runaway") (call $runaway))
106 |
107 | (func $mutual-runaway1 (export "mutual-runaway") (call $mutual-runaway2))
108 | (func $mutual-runaway2 (call $mutual-runaway1))
109 | )
110 |
111 | (assert_return (invoke "type-i32") (i32.const 0x132))
112 | (assert_return (invoke "type-i64") (i64.const 0x164))
113 | (assert_return (invoke "type-f32") (f32.const 0xf32))
114 | (assert_return (invoke "type-f64") (f64.const 0xf64))
115 |
116 | (assert_return (invoke "type-first-i32") (i32.const 32))
117 | (assert_return (invoke "type-first-i64") (i64.const 64))
118 | (assert_return (invoke "type-first-f32") (f32.const 1.32))
119 | (assert_return (invoke "type-first-f64") (f64.const 1.64))
120 |
121 | (assert_return (invoke "type-second-i32") (i32.const 32))
122 | (assert_return (invoke "type-second-i64") (i64.const 64))
123 | (assert_return (invoke "type-second-f32") (f32.const 32))
124 | (assert_return (invoke "type-second-f64") (f64.const 64.1))
125 |
126 | (assert_return (invoke "fac" (i64.const 0)) (i64.const 1))
127 | (assert_return (invoke "fac" (i64.const 1)) (i64.const 1))
128 | (assert_return (invoke "fac" (i64.const 5)) (i64.const 120))
129 | (assert_return (invoke "fac" (i64.const 25)) (i64.const 7034535277573963776))
130 | (assert_return (invoke "fac-acc" (i64.const 0) (i64.const 1)) (i64.const 1))
131 | (assert_return (invoke "fac-acc" (i64.const 1) (i64.const 1)) (i64.const 1))
132 | (assert_return (invoke "fac-acc" (i64.const 5) (i64.const 1)) (i64.const 120))
133 | (assert_return
134 | (invoke "fac-acc" (i64.const 25) (i64.const 1))
135 | (i64.const 7034535277573963776)
136 | )
137 |
138 | (assert_return (invoke "fib" (i64.const 0)) (i64.const 1))
139 | (assert_return (invoke "fib" (i64.const 1)) (i64.const 1))
140 | (assert_return (invoke "fib" (i64.const 2)) (i64.const 2))
141 | (assert_return (invoke "fib" (i64.const 5)) (i64.const 8))
142 | (assert_return (invoke "fib" (i64.const 20)) (i64.const 10946))
143 |
144 | (assert_return (invoke "even" (i64.const 0)) (i32.const 44))
145 | (assert_return (invoke "even" (i64.const 1)) (i32.const 99))
146 | (assert_return (invoke "even" (i64.const 100)) (i32.const 44))
147 | (assert_return (invoke "even" (i64.const 77)) (i32.const 99))
148 | (assert_return (invoke "odd" (i64.const 0)) (i32.const 99))
149 | (assert_return (invoke "odd" (i64.const 1)) (i32.const 44))
150 | (assert_return (invoke "odd" (i64.const 200)) (i32.const 99))
151 | (assert_return (invoke "odd" (i64.const 77)) (i32.const 44))
152 |
153 | (assert_exhaustion (invoke "runaway") "call stack exhausted")
154 | (assert_exhaustion (invoke "mutual-runaway") "call stack exhausted")
155 |
156 |
157 | ;; Invalid typing
158 |
159 | (assert_invalid
160 | (module
161 | (func $type-void-vs-num (i32.eqz (call 1)))
162 | (func)
163 | )
164 | "type mismatch"
165 | )
166 | (assert_invalid
167 | (module
168 | (func $type-num-vs-num (i32.eqz (call 1)))
169 | (func (result i64) (i64.const 1))
170 | )
171 | "type mismatch"
172 | )
173 |
174 | (assert_invalid
175 | (module
176 | (func $arity-0-vs-1 (call 1))
177 | (func (param i32))
178 | )
179 | "type mismatch"
180 | )
181 | (assert_invalid
182 | (module
183 | (func $arity-0-vs-2 (call 1))
184 | (func (param f64 i32))
185 | )
186 | "type mismatch"
187 | )
188 | (assert_invalid
189 | (module
190 | (func $arity-1-vs-0 (call 1 (i32.const 1)))
191 | (func)
192 | )
193 | "type mismatch"
194 | )
195 | (assert_invalid
196 | (module
197 | (func $arity-2-vs-0 (call 1 (f64.const 2) (i32.const 1)))
198 | (func)
199 | )
200 | "type mismatch"
201 | )
202 |
203 | (assert_invalid
204 | (module
205 | (func $type-first-void-vs-num (call 1 (nop) (i32.const 1)))
206 | (func (param i32 i32))
207 | )
208 | "type mismatch"
209 | )
210 | (assert_invalid
211 | (module
212 | (func $type-second-void-vs-num (call 1 (i32.const 1) (nop)))
213 | (func (param i32 i32))
214 | )
215 | "type mismatch"
216 | )
217 | (assert_invalid
218 | (module
219 | (func $type-first-num-vs-num (call 1 (f64.const 1) (i32.const 1)))
220 | (func (param i32 f64))
221 | )
222 | "type mismatch"
223 | )
224 | (assert_invalid
225 | (module
226 | (func $type-second-num-vs-num (call 1 (i32.const 1) (f64.const 1)))
227 | (func (param f64 i32))
228 | )
229 | "type mismatch"
230 | )
231 |
232 |
233 | ;; Unbound function
234 |
235 | (assert_invalid
236 | (module (func $unbound-func (call 1)))
237 | "unknown function"
238 | )
239 | (assert_invalid
240 | (module (func $large-func (call 1012321300)))
241 | "unknown function"
242 | )
243 |
--------------------------------------------------------------------------------
/tests/failing/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 | (;Heiße Würstchen;)
43 |
44 | (;;)
45 |
46 | (;comment
47 | comment;)
48 |
49 | (;comment;)
50 |
51 | (;comment;)((;comment;)
52 | (;comment;)module(;comment;)
53 | (;comment;))(;comment;)
54 |
55 | (;comment(;nested;)comment;)
56 |
57 | (;comment
58 | (;nested
59 | ;)comment
60 | ;)
61 |
62 | (module
63 | (;comment(;nested(;further;)nested;)comment;)
64 | )
65 |
66 | (;comment;;comment;)
67 |
68 | (;comment;;comment
69 | ;)
70 |
71 | (module
72 | (;comment;;comment(;nested;)comment;)
73 | )
--------------------------------------------------------------------------------
/tests/failing/const.wast:
--------------------------------------------------------------------------------
1 | ;; Test t.const instructions
2 |
3 | ;; Syntax error
4 |
5 | (module (func (i32.const 0xffffffff) drop))
6 | (module (func (i32.const -0x80000000) drop))
7 | (assert_malformed
8 | (module quote "(func (i32.const 0x100000000) drop)")
9 | "constant out of range"
10 | )
11 | (assert_malformed
12 | (module quote "(func (i32.const -0x80000001) drop)")
13 | "constant out of range"
14 | )
15 |
16 | (module (func (i32.const 4294967295) drop))
17 | (module (func (i32.const -2147483648) drop))
18 | (assert_malformed
19 | (module quote "(func (i32.const 4294967296) drop)")
20 | "constant out of range"
21 | )
22 | (assert_malformed
23 | (module quote "(func (i32.const -2147483649) drop)")
24 | "constant out of range"
25 | )
26 |
27 | (module (func (i64.const 0xffffffffffffffff) drop))
28 | (module (func (i64.const -0x8000000000000000) drop))
29 | (assert_malformed
30 | (module quote "(func (i64.const 0x10000000000000000) drop)")
31 | "constant out of range"
32 | )
33 | (assert_malformed
34 | (module quote "(func (i64.const -0x8000000000000001) drop)")
35 | "constant out of range"
36 | )
37 |
38 | (module (func (i64.const 18446744073709551615) drop))
39 | (module (func (i64.const -9223372036854775808) drop))
40 | (assert_malformed
41 | (module quote "(func (i64.const 18446744073709551616) drop)")
42 | "constant out of range"
43 | )
44 | (assert_malformed
45 | (module quote "(func (i64.const -9223372036854775809) drop)")
46 | "constant out of range"
47 | )
48 |
49 | (module (func (f32.const 0x1p127) drop))
50 | (module (func (f32.const -0x1p127) drop))
51 | (module (func (f32.const 0x1.fffffep127) drop))
52 | (module (func (f32.const -0x1.fffffep127) drop))
53 | (module (func (f32.const 0x1.fffffe7p127) drop))
54 | (module (func (f32.const -0x1.fffffe7p127) drop))
55 | (assert_malformed
56 | (module quote "(func (f32.const 0x1p128) drop)")
57 | "constant out of range"
58 | )
59 | (assert_malformed
60 | (module quote "(func (f32.const -0x1p128) drop)")
61 | "constant out of range"
62 | )
63 | (assert_malformed
64 | (module quote "(func (f32.const 0x1.ffffffp127) drop)")
65 | "constant out of range"
66 | )
67 | (assert_malformed
68 | (module quote "(func (f32.const -0x1.ffffffp127) drop)")
69 | "constant out of range"
70 | )
71 |
72 | (module (func (f32.const 1e38) drop))
73 | (module (func (f32.const -1e38) drop))
74 | (assert_malformed
75 | (module quote "(func (f32.const 1e39) drop)")
76 | "constant out of range"
77 | )
78 | (assert_malformed
79 | (module quote "(func (f32.const -1e39) drop)")
80 | "constant out of range"
81 | )
82 |
83 | (module (func (f32.const 340282356779733623858607532500980858880) drop))
84 | (module (func (f32.const -340282356779733623858607532500980858880) drop))
85 | (assert_malformed
86 | (module quote "(func (f32.const 340282356779733661637539395458142568448) drop)")
87 | "constant out of range"
88 | )
89 | (assert_malformed
90 | (module quote "(func (f32.const -340282356779733661637539395458142568448) drop)")
91 | "constant out of range"
92 | )
93 |
94 | (module (func (f64.const 0x1p1023) drop))
95 | (module (func (f64.const -0x1p1023) drop))
96 | (module (func (f64.const 0x1.fffffffffffffp1023) drop))
97 | (module (func (f64.const -0x1.fffffffffffffp1023) drop))
98 | (module (func (f64.const 0x1.fffffffffffff7p1023) drop))
99 | (module (func (f64.const -0x1.fffffffffffff7p1023) drop))
100 | (assert_malformed
101 | (module quote "(func (f64.const 0x1p1024) drop)")
102 | "constant out of range"
103 | )
104 | (assert_malformed
105 | (module quote "(func (f64.const -0x1p1024) drop)")
106 | "constant out of range"
107 | )
108 | (assert_malformed
109 | (module quote "(func (f64.const 0x1.fffffffffffff8p1023) drop)")
110 | "constant out of range"
111 | )
112 | (assert_malformed
113 | (module quote "(func (f64.const -0x1.fffffffffffff8p1023) drop)")
114 | "constant out of range"
115 | )
116 |
117 | (module (func (f64.const 1e308) drop))
118 | (module (func (f64.const -1e308) drop))
119 | (assert_malformed
120 | (module quote "(func (f64.const 1e309) drop)")
121 | "constant out of range"
122 | )
123 | (assert_malformed
124 | (module quote "(func (f64.const -1e309) drop)")
125 | "constant out of range"
126 | )
127 |
128 | (module (func (f64.const 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368) drop))
129 | (module (func (f64.const -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368) drop))
130 | (assert_malformed
131 | (module quote "(func (f64.const 269653970229347356221791135597556535197105851288767494898376215204735891170042808140884337949150317257310688430271573696351481990334196274152701320055306275479074865864826923114368235135583993416113802762682700913456874855354834422248712838998185022412196739306217084753107265771378949821875606039276187287552) drop)")
132 | "constant out of range"
133 | )
134 | (assert_malformed
135 | (module quote "(func (f64.const -269653970229347356221791135597556535197105851288767494898376215204735891170042808140884337949150317257310688430271573696351481990334196274152701320055306275479074865864826923114368235135583993416113802762682700913456874855354834422248712838998185022412196739306217084753107265771378949821875606039276187287552) drop)")
136 | "constant out of range"
137 | )
138 |
--------------------------------------------------------------------------------
/tests/failing/custom_section.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\26\10" "a custom section" "this is the payload"
80 | )
81 | "unexpected end"
82 | )
83 |
84 | (assert_malformed
85 | (module binary
86 | "\00asm" "\01\00\00\00"
87 | "\00\25\10" "a custom section" "this is the payload"
88 | "\00\24\10" "a custom section" "this is the payload"
89 | )
90 | "invalid section id"
91 | )
92 |
93 | (assert_malformed
94 | (module binary
95 | "\00asm" "\01\00\00\00"
96 | "\01\07\01\60\02\7f\7f\01\7f" ;; type section
97 | "\00\25\10" "a custom section" "this is the payload" ;; invalid length!
98 | "\03\02\01\00" ;; function section
99 | "\0a\09\01\07\00\20\00\20\01\6a\0b" ;; code section
100 | "\00\1b\07" "custom2" "this is the payload" ;; custom section
101 | )
102 | "function and code section have inconsistent lengths"
103 | )
104 |
105 | ;; Test concatenated modules.
106 | (assert_malformed
107 | (module binary
108 | "\00asm\01\00\00\00"
109 | "\00asm\01\00\00\00"
110 | )
111 | "length out of bounds"
112 | )
113 |
--------------------------------------------------------------------------------
/tests/failing/elem.wast:
--------------------------------------------------------------------------------
1 | ;; Test the element section
2 |
3 | (module
4 | (table 10 anyfunc)
5 | (elem (i32.const 0) $f)
6 | (func $f)
7 | )
8 |
9 | (module
10 | (table 10 anyfunc)
11 | (elem (i32.const 9) $f)
12 | (func $f)
13 | )
14 |
15 | (module
16 | (type $out-i32 (func (result i32)))
17 | (table 10 anyfunc)
18 | (elem (i32.const 7) $const-i32-a)
19 | (elem (i32.const 9) $const-i32-b)
20 | (func $const-i32-a (type $out-i32) (i32.const 65))
21 | (func $const-i32-b (type $out-i32) (i32.const 66))
22 | (func (export "call-7") (type $out-i32)
23 | (call_indirect (type $out-i32) (i32.const 7))
24 | )
25 | (func (export "call-9") (type $out-i32)
26 | (call_indirect (type $out-i32) (i32.const 9))
27 | )
28 | )
29 |
30 | (assert_return (invoke "call-7") (i32.const 65))
31 | (assert_return (invoke "call-9") (i32.const 66))
32 |
33 | ;; Two elements target the same slot
34 |
35 | (module
36 | (type $out-i32 (func (result i32)))
37 | (table 10 anyfunc)
38 | (elem (i32.const 9) $const-i32-a)
39 | (elem (i32.const 9) $const-i32-b)
40 | (func $const-i32-a (type $out-i32) (i32.const 65))
41 | (func $const-i32-b (type $out-i32) (i32.const 66))
42 | (func (export "call-overwritten-element") (type $out-i32)
43 | (call_indirect (type $out-i32) (i32.const 9))
44 | )
45 | )
46 |
47 | (assert_return (invoke "call-overwritten-element") (i32.const 66))
48 |
49 | ;; Invalid bounds for elements
50 |
51 | (assert_unlinkable
52 | (module
53 | (table 10 anyfunc)
54 | (elem (i32.const 10) $f)
55 | (func $f)
56 | )
57 | "elements segment does not fit"
58 | )
59 |
60 | (assert_unlinkable
61 | (module
62 | (table 10 20 anyfunc)
63 | (elem (i32.const 10) $f)
64 | (func $f)
65 | )
66 | "elements segment does not fit"
67 | )
68 |
69 | (assert_unlinkable
70 | (module
71 | (table 10 anyfunc)
72 | (elem (i32.const -1) $f)
73 | (func $f)
74 | )
75 | "elements segment does not fit"
76 | )
77 |
78 | (assert_unlinkable
79 | (module
80 | (table 10 anyfunc)
81 | (elem (i32.const -10) $f)
82 | (func $f)
83 | )
84 | "elements segment does not fit"
85 | )
86 |
87 | ;; Tests with an imported table
88 |
89 | (module
90 | (import "spectest" "table" (table 10 anyfunc))
91 | (elem (i32.const 0) $f)
92 | (func $f)
93 | )
94 |
95 | (module
96 | (import "spectest" "table" (table 10 anyfunc))
97 | (elem (i32.const 9) $f)
98 | (func $f)
99 | )
100 |
101 | ;; Two elements target the same slot
102 |
103 | (module
104 | (type $out-i32 (func (result i32)))
105 | (import "spectest" "table" (table 10 anyfunc))
106 | (elem (i32.const 9) $const-i32-a)
107 | (elem (i32.const 9) $const-i32-b)
108 | (func $const-i32-a (type $out-i32) (i32.const 65))
109 | (func $const-i32-b (type $out-i32) (i32.const 66))
110 | (func (export "call-overwritten-element") (type $out-i32)
111 | (call_indirect (type $out-i32) (i32.const 9))
112 | )
113 | )
114 |
115 | (assert_return (invoke "call-overwritten-element") (i32.const 66))
116 |
117 | ;; Invalid bounds for elements
118 |
119 | (assert_unlinkable
120 | (module
121 | (import "spectest" "table" (table 10 anyfunc))
122 | (elem (i32.const 10) $f)
123 | (func $f)
124 | )
125 | "elements segment does not fit"
126 | )
127 |
128 | (assert_unlinkable
129 | (module
130 | (import "spectest" "table" (table 10 20 anyfunc))
131 | (elem (i32.const 10) $f)
132 | (func $f)
133 | )
134 | "elements segment does not fit"
135 | )
136 |
137 | (assert_unlinkable
138 | (module
139 | (import "spectest" "table" (table 10 anyfunc))
140 | (elem (i32.const -1) $f)
141 | (func $f)
142 | )
143 | "elements segment does not fit"
144 | )
145 |
146 | (assert_unlinkable
147 | (module
148 | (import "spectest" "table" (table 10 anyfunc))
149 | (elem (i32.const -10) $f)
150 | (func $f)
151 | )
152 | "elements segment does not fit"
153 | )
154 |
155 | ;; Element without table
156 |
157 | (assert_invalid
158 | (module
159 | (elem (i32.const 0) $f)
160 | (func $f)
161 | )
162 | "unknown table 0"
163 | )
164 |
165 | ;; Test element sections across multiple modules change the same table
166 |
167 | (module $module1
168 | (type $out-i32 (func (result i32)))
169 | (table (export "shared-table") 10 anyfunc)
170 | (elem (i32.const 8) $const-i32-a)
171 | (elem (i32.const 9) $const-i32-b)
172 | (func $const-i32-a (type $out-i32) (i32.const 65))
173 | (func $const-i32-b (type $out-i32) (i32.const 66))
174 | (func (export "call-7") (type $out-i32)
175 | (call_indirect (type $out-i32) (i32.const 7))
176 | )
177 | (func (export "call-8") (type $out-i32)
178 | (call_indirect (type $out-i32) (i32.const 8))
179 | )
180 | (func (export "call-9") (type $out-i32)
181 | (call_indirect (type $out-i32) (i32.const 9))
182 | )
183 | )
184 |
185 | (register "module1" $module1)
186 |
187 | (assert_trap (invoke $module1 "call-7") "uninitialized element 7")
188 | (assert_return (invoke $module1 "call-8") (i32.const 65))
189 | (assert_return (invoke $module1 "call-9") (i32.const 66))
190 |
191 | (module $module2
192 | (type $out-i32 (func (result i32)))
193 | (import "module1" "shared-table" (table 10 anyfunc))
194 | (elem (i32.const 7) $const-i32-c)
195 | (elem (i32.const 8) $const-i32-d)
196 | (func $const-i32-c (type $out-i32) (i32.const 67))
197 | (func $const-i32-d (type $out-i32) (i32.const 68))
198 | )
199 |
200 | (assert_return (invoke $module1 "call-7") (i32.const 67))
201 | (assert_return (invoke $module1 "call-8") (i32.const 68))
202 | (assert_return (invoke $module1 "call-9") (i32.const 66))
203 |
204 | (module $module3
205 | (type $out-i32 (func (result i32)))
206 | (import "module1" "shared-table" (table 10 anyfunc))
207 | (elem (i32.const 8) $const-i32-e)
208 | (elem (i32.const 9) $const-i32-f)
209 | (func $const-i32-e (type $out-i32) (i32.const 69))
210 | (func $const-i32-f (type $out-i32) (i32.const 70))
211 | )
212 |
213 | (assert_return (invoke $module1 "call-7") (i32.const 67))
214 | (assert_return (invoke $module1 "call-8") (i32.const 69))
215 | (assert_return (invoke $module1 "call-9") (i32.const 70))
216 |
--------------------------------------------------------------------------------
/tests/failing/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 (get_local $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 | (assert_invalid
29 | (module (func) (export "a" (func 1)))
30 | "unknown function"
31 | )
32 | (assert_invalid
33 | (module (func) (export "a" (func 0)) (export "a" (func 0)))
34 | "duplicate export name"
35 | )
36 | (assert_invalid
37 | (module (func) (func) (export "a" (func 0)) (export "a" (func 1)))
38 | "duplicate export name"
39 | )
40 | (assert_invalid
41 | (module (func) (global i32 (i32.const 0)) (export "a" (func 0)) (export "a" (global 0)))
42 | "duplicate export name"
43 | )
44 | (assert_invalid
45 | (module (func) (table 0 anyfunc) (export "a" (func 0)) (export "a" (table 0)))
46 | "duplicate export name"
47 | )
48 | (assert_invalid
49 | (module (func) (memory 0) (export "a" (func 0)) (export "a" (memory 0)))
50 | "duplicate export name"
51 | )
52 |
53 |
54 | ;; Globals
55 |
56 | (module (global i32 (i32.const 0)) (export "a" (global 0)))
57 | (module (global i32 (i32.const 0)) (export "a" (global 0)) (export "b" (global 0)))
58 | (module (global i32 (i32.const 0)) (global i32 (i32.const 0)) (export "a" (global 0)) (export "b" (global 1)))
59 |
60 | (module (global (export "a") i32 (i32.const 0)))
61 | (module (global i32 (i32.const 0)) (export "a" (global 0)))
62 | (module (global $a (export "a") i32 (i32.const 0)))
63 | (module (global $a i32 (i32.const 0)) (export "a" (global $a)))
64 | (module (export "a" (global 0)) (global i32 (i32.const 0)))
65 | (module (export "a" (global $a)) (global $a i32 (i32.const 0)))
66 |
67 | (module $Global
68 | (export "e" (global $g))
69 | (global $g i32 (i32.const 42))
70 | )
71 | (assert_return (get "e") (i32.const 42))
72 | (assert_return (get $Global "e") (i32.const 42))
73 | (module)
74 | (module $Other2)
75 | (assert_return (get $Global "e") (i32.const 42))
76 |
77 | (assert_invalid
78 | (module (global i32 (i32.const 0)) (export "a" (global 1)))
79 | "unknown global"
80 | )
81 | (assert_invalid
82 | (module (global i32 (i32.const 0)) (export "a" (global 0)) (export "a" (global 0)))
83 | "duplicate export name"
84 | )
85 | (assert_invalid
86 | (module (global i32 (i32.const 0)) (global i32 (i32.const 0)) (export "a" (global 0)) (export "a" (global 1)))
87 | "duplicate export name"
88 | )
89 | (assert_invalid
90 | (module (global i32 (i32.const 0)) (func) (export "a" (global 0)) (export "a" (func 0)))
91 | "duplicate export name"
92 | )
93 | (assert_invalid
94 | (module (global i32 (i32.const 0)) (table 0 anyfunc) (export "a" (global 0)) (export "a" (table 0)))
95 | "duplicate export name"
96 | )
97 | (assert_invalid
98 | (module (global i32 (i32.const 0)) (memory 0) (export "a" (global 0)) (export "a" (memory 0)))
99 | "duplicate export name"
100 | )
101 |
102 |
103 | ;; Tables
104 |
105 | (module (table 0 anyfunc) (export "a" (table 0)))
106 | (module (table 0 anyfunc) (export "a" (table 0)) (export "b" (table 0)))
107 | ;; No multiple tables yet.
108 | ;; (module (table 0 anyfunc) (table 0 anyfunc) (export "a" (table 0)) (export "b" (table 1)))
109 |
110 | (module (table (export "a") 0 anyfunc))
111 | (module (table (export "a") 0 1 anyfunc))
112 | (module (table 0 anyfunc) (export "a" (table 0)))
113 | (module (table 0 1 anyfunc) (export "a" (table 0)))
114 | (module (table $a (export "a") 0 anyfunc))
115 | (module (table $a (export "a") 0 1 anyfunc))
116 | (module (table $a 0 anyfunc) (export "a" (table $a)))
117 | (module (table $a 0 1 anyfunc) (export "a" (table $a)))
118 | (module (export "a" (table 0)) (table 0 anyfunc))
119 | (module (export "a" (table 0)) (table 0 1 anyfunc))
120 | (module (export "a" (table $a)) (table $a 0 anyfunc))
121 | (module (export "a" (table $a)) (table $a 0 1 anyfunc))
122 |
123 | (; TODO: access table ;)
124 |
125 | (assert_invalid
126 | (module (table 0 anyfunc) (export "a" (table 1)))
127 | "unknown table"
128 | )
129 | (assert_invalid
130 | (module (table 0 anyfunc) (export "a" (table 0)) (export "a" (table 0)))
131 | "duplicate export name"
132 | )
133 | ;; No multiple tables yet.
134 | ;; (assert_invalid
135 | ;; (module (table 0 anyfunc) (table 0 anyfunc) (export "a" (table 0)) (export "a" (table 1)))
136 | ;; "duplicate export name"
137 | ;; )
138 | (assert_invalid
139 | (module (table 0 anyfunc) (func) (export "a" (table 0)) (export "a" (func 0)))
140 | "duplicate export name"
141 | )
142 | (assert_invalid
143 | (module (table 0 anyfunc) (global i32 (i32.const 0)) (export "a" (table 0)) (export "a" (global 0)))
144 | "duplicate export name"
145 | )
146 | (assert_invalid
147 | (module (table 0 anyfunc) (memory 0) (export "a" (table 0)) (export "a" (memory 0)))
148 | "duplicate export name"
149 | )
150 |
151 |
152 | ;; Memories
153 |
154 | (module (memory 0) (export "a" (memory 0)))
155 | (module (memory 0) (export "a" (memory 0)) (export "b" (memory 0)))
156 | ;; No multiple memories yet.
157 | ;; (module (memory 0) (memory 0) (export "a" (memory 0)) (export "b" (memory 1)))
158 |
159 | (module (memory (export "a") 0))
160 | (module (memory (export "a") 0 1))
161 | (module (memory 0) (export "a" (memory 0)))
162 | (module (memory 0 1) (export "a" (memory 0)))
163 | (module (memory $a (export "a") 0))
164 | (module (memory $a (export "a") 0 1))
165 | (module (memory $a 0) (export "a" (memory $a)))
166 | (module (memory $a 0 1) (export "a" (memory $a)))
167 | (module (export "a" (memory 0)) (memory 0))
168 | (module (export "a" (memory 0)) (memory 0 1))
169 | (module (export "a" (memory $a)) (memory $a 0))
170 | (module (export "a" (memory $a)) (memory $a 0 1))
171 |
172 | (; TODO: access memory ;)
173 |
174 | (assert_invalid
175 | (module (memory 0) (export "a" (memory 1)))
176 | "unknown memory"
177 | )
178 | (assert_invalid
179 | (module (memory 0) (export "a" (memory 0)) (export "a" (memory 0)))
180 | "duplicate export name"
181 | )
182 | ;; No multiple memories yet.
183 | ;; (assert_invalid
184 | ;; (module (memory 0) (memory 0) (export "a" (memory 0)) (export "a" (memory 1)))
185 | ;; "duplicate export name"
186 | ;; )
187 | (assert_invalid
188 | (module (memory 0) (func) (export "a" (memory 0)) (export "a" (func 0)))
189 | "duplicate export name"
190 | )
191 | (assert_invalid
192 | (module (memory 0) (global i32 (i32.const 0)) (export "a" (memory 0)) (export "a" (global 0)))
193 | "duplicate export name"
194 | )
195 | (assert_invalid
196 | (module (memory 0) (table 0 anyfunc) (export "a" (memory 0)) (export "a" (table 0)))
197 | "duplicate export name"
198 | )
199 |
--------------------------------------------------------------------------------
/tests/failing/fac.wast:
--------------------------------------------------------------------------------
1 | (module
2 | ;; Recursive factorial
3 | (func (export "fac-rec") (param i64) (result i64)
4 | (if (result i64) (i64.eq (get_local 0) (i64.const 0))
5 | (then (i64.const 1))
6 | (else
7 | (i64.mul (get_local 0) (call 0 (i64.sub (get_local 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 (get_local $n) (i64.const 0))
15 | (then (i64.const 1))
16 | (else
17 | (i64.mul
18 | (get_local $n)
19 | (call $fac-rec-named (i64.sub (get_local $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 | (set_local 1 (get_local 0))
29 | (set_local 2 (i64.const 1))
30 | (block
31 | (loop
32 | (if
33 | (i64.eq (get_local 1) (i64.const 0))
34 | (then (br 2))
35 | (else
36 | (set_local 2 (i64.mul (get_local 1) (get_local 2)))
37 | (set_local 1 (i64.sub (get_local 1) (i64.const 1)))
38 | )
39 | )
40 | (br 0)
41 | )
42 | )
43 | (get_local 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 | (set_local $i (get_local $n))
51 | (set_local $res (i64.const 1))
52 | (block $done
53 | (loop $loop
54 | (if
55 | (i64.eq (get_local $i) (i64.const 0))
56 | (then (br $done))
57 | (else
58 | (set_local $res (i64.mul (get_local $i) (get_local $res)))
59 | (set_local $i (i64.sub (get_local $i) (i64.const 1)))
60 | )
61 | )
62 | (br $loop)
63 | )
64 | )
65 | (get_local $res)
66 | )
67 |
68 | ;; Optimized factorial.
69 | (func (export "fac-opt") (param i64) (result i64)
70 | (local i64)
71 | (set_local 1 (i64.const 1))
72 | (block
73 | (br_if 0 (i64.lt_s (get_local 0) (i64.const 2)))
74 | (loop
75 | (set_local 1 (i64.mul (get_local 1) (get_local 0)))
76 | (set_local 0 (i64.add (get_local 0) (i64.const -1)))
77 | (br_if 0 (i64.gt_s (get_local 0) (i64.const 1)))
78 | )
79 | )
80 | (get_local 1)
81 | )
82 | )
83 |
84 | (assert_return (invoke "fac-rec" (i64.const 25)) (i64.const 7034535277573963776))
85 | (assert_return (invoke "fac-iter" (i64.const 25)) (i64.const 7034535277573963776))
86 | (assert_return (invoke "fac-rec-named" (i64.const 25)) (i64.const 7034535277573963776))
87 | (assert_return (invoke "fac-iter-named" (i64.const 25)) (i64.const 7034535277573963776))
88 | (assert_return (invoke "fac-opt" (i64.const 25)) (i64.const 7034535277573963776))
89 | (assert_exhaustion (invoke "fac-rec" (i64.const 1073741824)) "call stack exhausted")
90 |
--------------------------------------------------------------------------------
/tests/failing/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 |
--------------------------------------------------------------------------------
/tests/failing/forward.wast:
--------------------------------------------------------------------------------
1 | (module
2 | (func $even (export "even") (param $n i32) (result i32)
3 | (if (result i32) (i32.eq (get_local $n) (i32.const 0))
4 | (then (i32.const 1))
5 | (else (call $odd (i32.sub (get_local $n) (i32.const 1))))
6 | )
7 | )
8 |
9 | (func $odd (export "odd") (param $n i32) (result i32)
10 | (if (result i32) (i32.eq (get_local $n) (i32.const 0))
11 | (then (i32.const 0))
12 | (else (call $even (i32.sub (get_local $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 |
--------------------------------------------------------------------------------
/tests/failing/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") (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 (get_local 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 (get_local 0) (i32.const 2))
22 | )
23 |
24 | (func (export "four") (type $U) (call $print (get_local 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 anyfunc) (elem (i64.const 0)))
37 | "type mismatch"
38 | )
39 | (assert_invalid
40 | (module (table 1 anyfunc) (elem (i32.ctz (i32.const 0))))
41 | "constant expression required"
42 | )
43 | (assert_invalid
44 | (module (table 1 anyfunc) (elem (nop)))
45 | "constant expression required"
46 | )
47 |
48 | (assert_invalid (module (func (type 42))) "unknown type")
49 | (assert_invalid (module (import "spectest" "print" (func (type 43)))) "unknown type")
50 |
51 | (module
52 | (type $T (func (param) (result i32)))
53 | (type $U (func (param) (result i32)))
54 | (table anyfunc (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) (get_local $i))
64 | )
65 |
66 | (func (export "callu") (param $i i32) (result i32)
67 | (call_indirect (type $U) (get_local $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 anyfunc (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) (get_local $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 |
--------------------------------------------------------------------------------
/tests/failing/get_local.wast:
--------------------------------------------------------------------------------
1 | ;; Test `get_local` operator
2 |
3 | (module
4 | ;; Typing
5 |
6 | (func (export "type-local-i32") (result i32) (local i32) (get_local 0))
7 | (func (export "type-local-i64") (result i64) (local i64) (get_local 0))
8 | (func (export "type-local-f32") (result f32) (local f32) (get_local 0))
9 | (func (export "type-local-f64") (result f64) (local f64) (get_local 0))
10 |
11 | (func (export "type-param-i32") (param i32) (result i32) (get_local 0))
12 | (func (export "type-param-i64") (param i64) (result i64) (get_local 0))
13 | (func (export "type-param-f32") (param f32) (result f32) (get_local 0))
14 | (func (export "type-param-f64") (param f64) (result f64) (get_local 0))
15 |
16 | (func (export "type-mixed") (param i64 f32 f64 i32 i32)
17 | (local f32 i64 i64 f64)
18 | (drop (i64.eqz (get_local 0)))
19 | (drop (f32.neg (get_local 1)))
20 | (drop (f64.neg (get_local 2)))
21 | (drop (i32.eqz (get_local 3)))
22 | (drop (i32.eqz (get_local 4)))
23 | (drop (f32.neg (get_local 5)))
24 | (drop (i64.eqz (get_local 6)))
25 | (drop (i64.eqz (get_local 7)))
26 | (drop (f64.neg (get_local 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 | (set_local 5 (f32.const 5.5))
34 | (set_local 6 (i64.const 6))
35 | (set_local 8 (f64.const 8))
36 | (f64.add
37 | (f64.convert_u/i64 (get_local 0))
38 | (f64.add
39 | (f64.promote/f32 (get_local 1))
40 | (f64.add
41 | (get_local 2)
42 | (f64.add
43 | (f64.convert_u/i32 (get_local 3))
44 | (f64.add
45 | (f64.convert_s/i32 (get_local 4))
46 | (f64.add
47 | (f64.promote/f32 (get_local 5))
48 | (f64.add
49 | (f64.convert_u/i64 (get_local 6))
50 | (f64.add
51 | (f64.convert_u/i64 (get_local 7))
52 | (get_local 8)
53 | )
54 | )
55 | )
56 | )
57 | )
58 | )
59 | )
60 | )
61 | )
62 | )
63 |
64 | (assert_return (invoke "type-local-i32") (i32.const 0))
65 | (assert_return (invoke "type-local-i64") (i64.const 0))
66 | (assert_return (invoke "type-local-f32") (f32.const 0))
67 | (assert_return (invoke "type-local-f64") (f64.const 0))
68 |
69 | (assert_return (invoke "type-param-i32" (i32.const 2)) (i32.const 2))
70 | (assert_return (invoke "type-param-i64" (i64.const 3)) (i64.const 3))
71 | (assert_return (invoke "type-param-f32" (f32.const 4.4)) (f32.const 4.4))
72 | (assert_return (invoke "type-param-f64" (f64.const 5.5)) (f64.const 5.5))
73 |
74 | (assert_return
75 | (invoke "type-mixed"
76 | (i64.const 1) (f32.const 2.2) (f64.const 3.3) (i32.const 4) (i32.const 5)
77 | )
78 | )
79 |
80 | (assert_return
81 | (invoke "read"
82 | (i64.const 1) (f32.const 2) (f64.const 3.3) (i32.const 4) (i32.const 5)
83 | )
84 | (f64.const 34.8)
85 | )
86 |
87 |
88 | ;; Invalid typing of access to locals
89 |
90 | (assert_invalid
91 | (module (func $type-local-num-vs-num (result i64) (local i32) (get_local 0)))
92 | "type mismatch"
93 | )
94 | (assert_invalid
95 | (module (func $type-local-num-vs-num (local f32) (i32.eqz (get_local 0))))
96 | "type mismatch"
97 | )
98 | (assert_invalid
99 | (module (func $type-local-num-vs-num (local f64 i64) (f64.neg (get_local 1))))
100 | "type mismatch"
101 | )
102 |
103 |
104 | ;; Invalid typing of access to parameters
105 |
106 | (assert_invalid
107 | (module (func $type-param-num-vs-num (param i32) (result i64) (get_local 0)))
108 | "type mismatch"
109 | )
110 | (assert_invalid
111 | (module (func $type-param-num-vs-num (param f32) (i32.eqz (get_local 0))))
112 | "type mismatch"
113 | )
114 | (assert_invalid
115 | (module (func $type-param-num-vs-num (param f64 i64) (f64.neg (get_local 1))))
116 | "type mismatch"
117 | )
118 |
119 |
120 | ;; Invalid local index
121 |
122 | (assert_invalid
123 | (module (func $unbound-local (local i32 i64) (get_local 3)))
124 | "unknown local"
125 | )
126 | (assert_invalid
127 | (module (func $large-local (local i32 i64) (get_local 14324343)))
128 | "unknown local"
129 | )
130 |
131 | (assert_invalid
132 | (module (func $unbound-param (param i32 i64) (get_local 2)))
133 | "unknown local"
134 | )
135 | (assert_invalid
136 | (module (func $large-param (local i32 i64) (get_local 714324343)))
137 | "unknown local"
138 | )
139 |
140 | (assert_invalid
141 | (module (func $unbound-mixed (param i32) (local i32 i64) (get_local 3)))
142 | "unknown local"
143 | )
144 | (assert_invalid
145 | (module (func $large-mixed (param i64) (local i32 i64) (get_local 214324343)))
146 | "unknown local"
147 | )
148 |
149 |
--------------------------------------------------------------------------------
/tests/failing/globals.wast:
--------------------------------------------------------------------------------
1 | ;; Test globals
2 |
3 | (module
4 | (global $a i32 (i32.const -2))
5 | (global (;1;) f32 (f32.const -3))
6 | (global (;2;) f64 (f64.const -4))
7 | (global $b i64 (i64.const -5))
8 |
9 | (global $x (mut i32) (i32.const -12))
10 | (global (;5;) (mut f32) (f32.const -13))
11 | (global (;6;) (mut f64) (f64.const -14))
12 | (global $y (mut i64) (i64.const -15))
13 |
14 | (func (export "get-a") (result i32) (get_global $a))
15 | (func (export "get-b") (result i64) (get_global $b))
16 | (func (export "get-x") (result i32) (get_global $x))
17 | (func (export "get-y") (result i64) (get_global $y))
18 | (func (export "set-x") (param i32) (set_global $x (get_local 0)))
19 | (func (export "set-y") (param i64) (set_global $y (get_local 0)))
20 |
21 | (func (export "get-1") (result f32) (get_global 1))
22 | (func (export "get-2") (result f64) (get_global 2))
23 | (func (export "get-5") (result f32) (get_global 5))
24 | (func (export "get-6") (result f64) (get_global 6))
25 | (func (export "set-5") (param f32) (set_global 5 (get_local 0)))
26 | (func (export "set-6") (param f64) (set_global 6 (get_local 0)))
27 | )
28 |
29 | (assert_return (invoke "get-a") (i32.const -2))
30 | (assert_return (invoke "get-b") (i64.const -5))
31 | (assert_return (invoke "get-x") (i32.const -12))
32 | (assert_return (invoke "get-y") (i64.const -15))
33 |
34 | (assert_return (invoke "get-1") (f32.const -3))
35 | (assert_return (invoke "get-2") (f64.const -4))
36 | (assert_return (invoke "get-5") (f32.const -13))
37 | (assert_return (invoke "get-6") (f64.const -14))
38 |
39 | (assert_return (invoke "set-x" (i32.const 6)))
40 | (assert_return (invoke "set-y" (i64.const 7)))
41 | (assert_return (invoke "set-5" (f32.const 8)))
42 | (assert_return (invoke "set-6" (f64.const 9)))
43 |
44 | (assert_return (invoke "get-x") (i32.const 6))
45 | (assert_return (invoke "get-y") (i64.const 7))
46 | (assert_return (invoke "get-5") (f32.const 8))
47 | (assert_return (invoke "get-6") (f64.const 9))
48 |
49 | (assert_invalid
50 | (module (global f32 (f32.const 0)) (func (set_global 0 (i32.const 1))))
51 | "global is immutable"
52 | )
53 |
54 | (assert_invalid
55 | (module (import "m" "a" (global (mut i32))))
56 | "mutable globals cannot be imported"
57 | )
58 |
59 | (assert_invalid
60 | (module (global (import "m" "a") (mut i32)))
61 | "mutable globals cannot be imported"
62 | )
63 |
64 | (assert_invalid
65 | (module (global (mut f32) (f32.const 0)) (export "a" (global 0)))
66 | "mutable globals cannot be exported"
67 | )
68 |
69 | (assert_invalid
70 | (module (global (export "a") (mut f32) (f32.const 0)))
71 | "mutable globals cannot be exported"
72 | )
73 |
74 | (assert_invalid
75 | (module (global f32 (f32.neg (f32.const 0))))
76 | "constant expression required"
77 | )
78 |
79 | (assert_invalid
80 | (module (global f32 (get_local 0)))
81 | "constant expression required"
82 | )
83 |
84 | (assert_invalid
85 | (module (global f32 (f32.neg (f32.const 1))))
86 | "constant expression required"
87 | )
88 |
89 | (assert_invalid
90 | (module (global i32 (i32.const 0) (nop)))
91 | "constant expression required"
92 | )
93 |
94 | (assert_invalid
95 | (module (global i32 (nop)))
96 | "constant expression required"
97 | )
98 |
99 | (assert_invalid
100 | (module (global i32 (f32.const 0)))
101 | "type mismatch"
102 | )
103 |
104 | (assert_invalid
105 | (module (global i32 (i32.const 0) (i32.const 0)))
106 | "type mismatch"
107 | )
108 |
109 | (assert_invalid
110 | (module (global i32 (;empty instruction sequence;)))
111 | "type mismatch"
112 | )
113 |
114 | (assert_invalid
115 | (module (global i32 (get_global 0)))
116 | "unknown global"
117 | )
118 |
119 | (assert_invalid
120 | (module (global i32 (get_global 1)) (global i32 (i32.const 0)))
121 | "unknown global"
122 | )
123 |
124 | (module
125 | (import "spectest" "global" (global i32))
126 | )
127 | (assert_malformed
128 | (module binary
129 | "\00asm" "\01\00\00\00"
130 | "\02\94\80\80\80\00" ;; import section
131 | "\01" ;; length 1
132 | "\08\73\70\65\63\74\65\73\74" ;; "spectest"
133 | "\06\67\6c\6f\62\61\6c" ;; "global"
134 | "\03" ;; GlobalImport
135 | "\7f" ;; i32
136 | "\02" ;; invalid mutability
137 | )
138 | "invalid mutability"
139 | )
140 | (assert_malformed
141 | (module binary
142 | "\00asm" "\01\00\00\00"
143 | "\02\94\80\80\80\00" ;; import section
144 | "\01" ;; length 1
145 | "\08\73\70\65\63\74\65\73\74" ;; "spectest"
146 | "\06\67\6c\6f\62\61\6c" ;; "global"
147 | "\03" ;; GlobalImport
148 | "\7f" ;; i32
149 | "\ff" ;; invalid mutability
150 | )
151 | "invalid mutability"
152 | )
153 |
154 | (module
155 | (global i32 (i32.const 0))
156 | )
157 | (assert_malformed
158 | (module binary
159 | "\00asm" "\01\00\00\00"
160 | "\06\86\80\80\80\00" ;; global section
161 | "\01" ;; length 1
162 | "\7f" ;; i32
163 | "\02" ;; invalid mutability
164 | "\41\00" ;; i32.const 0
165 | "\0b" ;; end
166 | )
167 | "invalid mutability"
168 | )
169 | (assert_malformed
170 | (module binary
171 | "\00asm" "\01\00\00\00"
172 | "\06\86\80\80\80\00" ;; global section
173 | "\01" ;; length 1
174 | "\7f" ;; i32
175 | "\ff" ;; invalid mutability
176 | "\41\00" ;; i32.const 0
177 | "\0b" ;; end
178 | )
179 | "invalid mutability"
180 | )
181 |
--------------------------------------------------------------------------------
/tests/failing/inline-module.wast:
--------------------------------------------------------------------------------
1 | (func) (memory 0) (func (export "f"))
2 |
--------------------------------------------------------------------------------
/tests/failing/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 |
--------------------------------------------------------------------------------
/tests/failing/labels.wast:
--------------------------------------------------------------------------------
1 | (module
2 | (func (export "block") (result i32)
3 | (block $exit (result i32)
4 | (br $exit (i32.const 1))
5 | (i32.const 0)
6 | )
7 | )
8 |
9 | (func (export "loop1") (result i32)
10 | (local $i i32)
11 | (set_local $i (i32.const 0))
12 | (block $exit (result i32)
13 | (loop $cont (result i32)
14 | (set_local $i (i32.add (get_local $i) (i32.const 1)))
15 | (if (i32.eq (get_local $i) (i32.const 5))
16 | (then (br $exit (get_local $i)))
17 | )
18 | (br $cont)
19 | )
20 | )
21 | )
22 |
23 | (func (export "loop2") (result i32)
24 | (local $i i32)
25 | (set_local $i (i32.const 0))
26 | (block $exit (result i32)
27 | (loop $cont (result i32)
28 | (set_local $i (i32.add (get_local $i) (i32.const 1)))
29 | (if (i32.eq (get_local $i) (i32.const 5))
30 | (then (br $cont))
31 | )
32 | (if (i32.eq (get_local $i) (i32.const 8))
33 | (then (br $exit (get_local $i)))
34 | )
35 | (set_local $i (i32.add (get_local $i) (i32.const 1)))
36 | (br $cont)
37 | )
38 | )
39 | )
40 |
41 | (func (export "loop3") (result i32)
42 | (local $i i32)
43 | (set_local $i (i32.const 0))
44 | (block $exit (result i32)
45 | (loop $cont (result i32)
46 | (set_local $i (i32.add (get_local $i) (i32.const 1)))
47 | (if (i32.eq (get_local $i) (i32.const 5))
48 | (then (br $exit (get_local $i)))
49 | )
50 | (get_local $i)
51 | )
52 | )
53 | )
54 |
55 | (func (export "loop4") (param $max i32) (result i32)
56 | (local $i i32)
57 | (set_local $i (i32.const 1))
58 | (block $exit (result i32)
59 | (loop $cont (result i32)
60 | (set_local $i (i32.add (get_local $i) (get_local $i)))
61 | (if (i32.gt_u (get_local $i) (get_local $max))
62 | (then (br $exit (get_local $i)))
63 | )
64 | (br $cont)
65 | )
66 | )
67 | )
68 |
69 | (func (export "loop5") (result i32)
70 | (i32.add
71 | (loop $l (result i32) (i32.const 1))
72 | (i32.const 1)
73 | )
74 | )
75 |
76 | (func (export "if") (result i32)
77 | (local $i i32)
78 | (set_local $i (i32.const 0))
79 | (block
80 | (if $l
81 | (i32.const 1)
82 | (then (br $l) (set_local $i (i32.const 666)))
83 | )
84 | (set_local $i (i32.add (get_local $i) (i32.const 1)))
85 | (if $l
86 | (i32.const 1)
87 | (then (br $l) (set_local $i (i32.const 666)))
88 | (else (set_local $i (i32.const 888)))
89 | )
90 | (set_local $i (i32.add (get_local $i) (i32.const 1)))
91 | (if $l
92 | (i32.const 1)
93 | (then (br $l) (set_local $i (i32.const 666)))
94 | (else (set_local $i (i32.const 888)))
95 | )
96 | (set_local $i (i32.add (get_local $i) (i32.const 1)))
97 | (if $l
98 | (i32.const 0)
99 | (then (set_local $i (i32.const 888)))
100 | (else (br $l) (set_local $i (i32.const 666)))
101 | )
102 | (set_local $i (i32.add (get_local $i) (i32.const 1)))
103 | (if $l
104 | (i32.const 0)
105 | (then (set_local $i (i32.const 888)))
106 | (else (br $l) (set_local $i (i32.const 666)))
107 | )
108 | (set_local $i (i32.add (get_local $i) (i32.const 1)))
109 | )
110 | (get_local $i)
111 | )
112 |
113 | (func (export "if2") (result i32)
114 | (local $i i32)
115 | (set_local $i (i32.const 0))
116 | (block
117 | (if
118 | (i32.const 1)
119 | (then (br 0) (set_local $i (i32.const 666)))
120 | )
121 | (set_local $i (i32.add (get_local $i) (i32.const 1)))
122 | (if
123 | (i32.const 1)
124 | (then (br 0) (set_local $i (i32.const 666)))
125 | (else (set_local $i (i32.const 888)))
126 | )
127 | (set_local $i (i32.add (get_local $i) (i32.const 1)))
128 | (if
129 | (i32.const 1)
130 | (then (br 0) (set_local $i (i32.const 666)))
131 | (else (set_local $i (i32.const 888)))
132 | )
133 | (set_local $i (i32.add (get_local $i) (i32.const 1)))
134 | (if
135 | (i32.const 0)
136 | (then (set_local $i (i32.const 888)))
137 | (else (br 0) (set_local $i (i32.const 666)))
138 | )
139 | (set_local $i (i32.add (get_local $i) (i32.const 1)))
140 | (if
141 | (i32.const 0)
142 | (then (set_local $i (i32.const 888)))
143 | (else (br 0) (set_local $i (i32.const 666)))
144 | )
145 | (set_local $i (i32.add (get_local $i) (i32.const 1)))
146 | )
147 | (get_local $i)
148 | )
149 |
150 | (func (export "switch") (param i32) (result i32)
151 | (block $ret (result i32)
152 | (i32.mul (i32.const 10)
153 | (block $exit (result i32)
154 | (block $0
155 | (block $default
156 | (block $3
157 | (block $2
158 | (block $1
159 | (br_table $0 $1 $2 $3 $default (get_local 0))
160 | ) ;; 1
161 | ) ;; 2
162 | (br $exit (i32.const 2))
163 | ) ;; 3
164 | (br $ret (i32.const 3))
165 | ) ;; default
166 | ) ;; 0
167 | (i32.const 5)
168 | )
169 | )
170 | )
171 | )
172 |
173 | (func (export "return") (param i32) (result i32)
174 | (block $default
175 | (block $1
176 | (block $0
177 | (br_table $0 $1 (get_local 0))
178 | (br $default)
179 | ) ;; 0
180 | (return (i32.const 0))
181 | ) ;; 1
182 | ) ;; default
183 | (i32.const 2)
184 | )
185 |
186 | (func (export "br_if0") (result i32)
187 | (local $i i32)
188 | (set_local $i (i32.const 0))
189 | (block $outer (result i32)
190 | (block $inner
191 | (br_if $inner (i32.const 0))
192 | (set_local $i (i32.or (get_local $i) (i32.const 0x1)))
193 | (br_if $inner (i32.const 1))
194 | (set_local $i (i32.or (get_local $i) (i32.const 0x2)))
195 | )
196 | (drop (br_if $outer
197 | (block (result i32)
198 | (set_local $i (i32.or (get_local $i) (i32.const 0x4)))
199 | (get_local $i)
200 | )
201 | (i32.const 0)
202 | ))
203 | (set_local $i (i32.or (get_local $i) (i32.const 0x8)))
204 | (drop (br_if $outer
205 | (block (result i32)
206 | (set_local $i (i32.or (get_local $i) (i32.const 0x10)))
207 | (get_local $i)
208 | )
209 | (i32.const 1)
210 | ))
211 | (set_local $i (i32.or (get_local $i) (i32.const 0x20))) (get_local $i)
212 | )
213 | )
214 |
215 | (func (export "br_if1") (result i32)
216 | (block $l0 (result i32)
217 | (drop
218 | (br_if $l0
219 | (block $l1 (result i32) (br $l1 (i32.const 1)))
220 | (i32.const 1)
221 | )
222 | )
223 | (i32.const 1)
224 | )
225 | )
226 |
227 | (func (export "br_if2") (result i32)
228 | (block $l0 (result i32)
229 | (if (i32.const 1)
230 | (then (br $l0 (block $l1 (result i32) (br $l1 (i32.const 1)))))
231 | )
232 | (i32.const 1)
233 | )
234 | )
235 |
236 | (func (export "br_if3") (result i32)
237 | (local $i1 i32)
238 | (drop
239 | (i32.add
240 | (block $l0 (result i32)
241 | (drop (br_if $l0
242 | (block (result i32) (set_local $i1 (i32.const 1)) (get_local $i1))
243 | (block (result i32) (set_local $i1 (i32.const 2)) (get_local $i1))
244 | ))
245 | (i32.const 0)
246 | )
247 | (i32.const 0)
248 | )
249 | )
250 | (get_local $i1)
251 | )
252 |
253 | (func (export "br") (result i32)
254 | (block $l0 (result i32)
255 | (if (i32.const 1)
256 | (then (br $l0 (block $l1 (result i32) (br $l1 (i32.const 1)))))
257 | (else (block (drop (block $l1 (result i32) (br $l1 (i32.const 1))))))
258 | )
259 | (i32.const 1)
260 | )
261 | )
262 |
263 | (func (export "shadowing") (result i32)
264 | (block $l1 (result i32) (i32.xor (br $l1 (i32.const 1)) (i32.const 2)))
265 | )
266 |
267 | (func (export "redefinition") (result i32)
268 | (block $l1 (result i32)
269 | (i32.add
270 | (block $l1 (result i32) (i32.const 2))
271 | (block $l1 (result i32) (br $l1 (i32.const 3)))
272 | )
273 | )
274 | )
275 | )
276 |
277 | (assert_return (invoke "block") (i32.const 1))
278 | (assert_return (invoke "loop1") (i32.const 5))
279 | (assert_return (invoke "loop2") (i32.const 8))
280 | (assert_return (invoke "loop3") (i32.const 1))
281 | (assert_return (invoke "loop4" (i32.const 8)) (i32.const 16))
282 | (assert_return (invoke "loop5") (i32.const 2))
283 | (assert_return (invoke "if") (i32.const 5))
284 | (assert_return (invoke "if2") (i32.const 5))
285 | (assert_return (invoke "switch" (i32.const 0)) (i32.const 50))
286 | (assert_return (invoke "switch" (i32.const 1)) (i32.const 20))
287 | (assert_return (invoke "switch" (i32.const 2)) (i32.const 20))
288 | (assert_return (invoke "switch" (i32.const 3)) (i32.const 3))
289 | (assert_return (invoke "switch" (i32.const 4)) (i32.const 50))
290 | (assert_return (invoke "switch" (i32.const 5)) (i32.const 50))
291 | (assert_return (invoke "return" (i32.const 0)) (i32.const 0))
292 | (assert_return (invoke "return" (i32.const 1)) (i32.const 2))
293 | (assert_return (invoke "return" (i32.const 2)) (i32.const 2))
294 | (assert_return (invoke "br_if0") (i32.const 0x1d))
295 | (assert_return (invoke "br_if1") (i32.const 1))
296 | (assert_return (invoke "br_if2") (i32.const 1))
297 | (assert_return (invoke "br_if3") (i32.const 2))
298 | (assert_return (invoke "br") (i32.const 1))
299 | (assert_return (invoke "shadowing") (i32.const 1))
300 | (assert_return (invoke "redefinition") (i32.const 5))
301 |
302 | (assert_invalid
303 | (module (func (block $l (f32.neg (br_if $l (i32.const 1))) (nop))))
304 | "type mismatch"
305 | )
306 | (assert_invalid
307 | (module (func (block $l (br_if $l (f32.const 0) (i32.const 1)))))
308 | "type mismatch"
309 | )
310 | (assert_invalid
311 | (module (func (block $l (br_if $l (f32.const 0) (i32.const 1)))))
312 | "type mismatch"
313 | )
314 |
--------------------------------------------------------------------------------
/tests/failing/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 | (set_local $t (i32.load (i32.const 8)))
25 | (i32.store (i32.const 5) (i32.const 0x80000000))
26 | (set_local $s (i32.load (i32.const 8)))
27 | (i32.add (get_local $t) (get_local $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 | (set_local $t (f32.load (i32.const 11)))
34 | (i32.store (i32.const 8) (i32.const 0))
35 | (get_local $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 | (set_local $x (call $malloc (i32.const 4)))
52 | (set_local $y (call $malloc (i32.const 4)))
53 | (i32.store (get_local $x) (i32.const 42))
54 | (i32.store (get_local $y) (i32.const 43))
55 | (i32.load (get_local $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 |
--------------------------------------------------------------------------------
/tests/failing/nop.wast:
--------------------------------------------------------------------------------
1 | ;; Test `nop` operator.
2 |
3 | (module
4 | ;; Auxiliary definitions
5 | (func $dummy)
6 | (func $3-ary (param i32 i32 i32) (result i32)
7 | get_local 0 get_local 1 get_local 2 i32.sub i32.add
8 | )
9 | (memory 1)
10 |
11 | (func (export "as-func-first") (result i32)
12 | (nop) (i32.const 1)
13 | )
14 | (func (export "as-func-mid") (result i32)
15 | (call $dummy) (nop) (i32.const 2)
16 | )
17 | (func (export "as-func-last") (result i32)
18 | (call $dummy) (i32.const 3) (nop)
19 | )
20 | (func (export "as-func-everywhere") (result i32)
21 | (nop) (nop) (call $dummy) (nop) (i32.const 4) (nop) (nop)
22 | )
23 |
24 | (func (export "as-drop-last") (param i32)
25 | (get_local 0) (nop) (drop)
26 | )
27 | (func (export "as-drop-everywhere") (param i32)
28 | (nop) (nop) (get_local 0) (nop) (nop) (drop)
29 | )
30 |
31 | (func (export "as-select-mid1") (param i32) (result i32)
32 | (get_local 0) (nop) (get_local 0) (get_local 0) (select)
33 | )
34 | (func (export "as-select-mid2") (param i32) (result i32)
35 | (get_local 0) (get_local 0) (nop) (get_local 0) (select)
36 | )
37 | (func (export "as-select-last") (param i32) (result i32)
38 | (get_local 0) (get_local 0) (get_local 0) (nop) (select)
39 | )
40 | (func (export "as-select-everywhere") (param i32) (result i32)
41 | (nop) (get_local 0) (nop) (nop) (get_local 0)
42 | (nop) (nop) (get_local 0) (nop) (nop) (select)
43 | )
44 |
45 | (func (export "as-block-first") (result i32)
46 | (block (result i32) (nop) (i32.const 2))
47 | )
48 | (func (export "as-block-mid") (result i32)
49 | (block (result i32) (call $dummy) (nop) (i32.const 2))
50 | )
51 | (func (export "as-block-last") (result i32)
52 | (block (result i32) (nop) (call $dummy) (i32.const 3) (nop))
53 | )
54 | (func (export "as-block-everywhere") (result i32)
55 | (block (result i32)
56 | (nop) (nop) (call $dummy) (nop) (i32.const 4) (nop) (nop)
57 | )
58 | )
59 |
60 | (func (export "as-loop-first") (result i32)
61 | (loop (result i32) (nop) (i32.const 2))
62 | )
63 | (func (export "as-loop-mid") (result i32)
64 | (loop (result i32) (call $dummy) (nop) (i32.const 2))
65 | )
66 | (func (export "as-loop-last") (result i32)
67 | (loop (result i32) (call $dummy) (i32.const 3) (nop))
68 | )
69 | (func (export "as-loop-everywhere") (result i32)
70 | (loop (result i32)
71 | (nop) (nop) (call $dummy) (nop) (i32.const 4) (nop) (nop)
72 | )
73 | )
74 |
75 | (func (export "as-if-condition") (param i32)
76 | (get_local 0) (nop) (if (then (call $dummy)))
77 | )
78 | (func (export "as-if-then") (param i32)
79 | (if (get_local 0) (then (nop)) (else (call $dummy)))
80 | )
81 | (func (export "as-if-else") (param i32)
82 | (if (get_local 0) (then (call $dummy)) (else (nop)))
83 | )
84 |
85 | (func (export "as-br-last") (param i32) (result i32)
86 | (block (result i32) (get_local 0) (nop) (br 0))
87 | )
88 | (func (export "as-br-everywhere") (param i32) (result i32)
89 | (block (result i32) (nop) (nop) (get_local 0) (nop) (nop) (br 0))
90 | )
91 |
92 | (func (export "as-br_if-mid") (param i32) (result i32)
93 | (block (result i32) (get_local 0) (nop) (get_local 0) (br_if 0))
94 | )
95 | (func (export "as-br_if-last") (param i32) (result i32)
96 | (block (result i32) (get_local 0) (get_local 0) (nop) (br_if 0))
97 | )
98 | (func (export "as-br_if-everywhere") (param i32) (result i32)
99 | (block (result i32)
100 | (nop) (nop) (get_local 0) (nop) (nop) (get_local 0) (nop) (nop)
101 | (br_if 0)
102 | )
103 | )
104 |
105 | (func (export "as-br_table-mid") (param i32) (result i32)
106 | (block (result i32) (get_local 0) (nop) (get_local 0) (br_table 0 0))
107 | )
108 | (func (export "as-br_table-last") (param i32) (result i32)
109 | (block (result i32) (get_local 0) (get_local 0) (nop) (br_table 0 0))
110 | )
111 | (func (export "as-br_table-everywhere") (param i32) (result i32)
112 | (block (result i32)
113 | (nop) (nop) (get_local 0) (nop) (nop) (get_local 0) (nop) (nop)
114 | (br_table 0 0)
115 | )
116 | )
117 |
118 | (func (export "as-return-last") (param i32) (result i32)
119 | (get_local 0) (nop) (return)
120 | )
121 | (func (export "as-return-everywhere") (param i32) (result i32)
122 | (nop) (nop) (get_local 0) (nop) (nop) (return)
123 | )
124 |
125 | (func (export "as-call-mid1") (param i32 i32 i32) (result i32)
126 | (get_local 0) (nop) (get_local 1) (get_local 2) (call $3-ary)
127 | )
128 | (func (export "as-call-mid2") (param i32 i32 i32) (result i32)
129 | (get_local 0) (get_local 1) (nop) (get_local 2) (call $3-ary)
130 | )
131 | (func (export "as-call-last") (param i32 i32 i32) (result i32)
132 | (get_local 0) (get_local 1) (get_local 2) (nop) (call $3-ary)
133 | )
134 | (func (export "as-call-everywhere") (param i32 i32 i32) (result i32)
135 | (nop) (nop) (get_local 0) (nop) (nop) (get_local 1)
136 | (nop) (nop) (get_local 2) (nop) (nop) (call $3-ary)
137 | )
138 |
139 | ;; TODO(stack): call_indirect, *_local, load*, store*
140 |
141 | (func (export "as-unary-last") (param i32) (result i32)
142 | (get_local 0) (nop) (i32.ctz)
143 | )
144 | (func (export "as-unary-everywhere") (param i32) (result i32)
145 | (nop) (nop) (get_local 0) (nop) (nop) (i32.ctz)
146 | )
147 |
148 | (func (export "as-binary-mid") (param i32) (result i32)
149 | (get_local 0) (nop) (get_local 0) (i32.add)
150 | )
151 | (func (export "as-binary-last") (param i32) (result i32)
152 | (get_local 0) (get_local 0) (nop) (i32.add)
153 | )
154 | (func (export "as-binary-everywhere") (param i32) (result i32)
155 | (nop) (get_local 0) (nop) (nop) (get_local 0) (nop) (nop) (i32.add)
156 | )
157 |
158 | (func (export "as-test-last") (param i32) (result i32)
159 | (get_local 0) (nop) (i32.eqz)
160 | )
161 | (func (export "as-test-everywhere") (param i32) (result i32)
162 | (nop) (nop) (get_local 0) (nop) (nop) i32.eqz
163 | )
164 |
165 | (func (export "as-compare-mid") (param i32) (result i32)
166 | (get_local 0) (nop) (get_local 0) (i32.ne)
167 | )
168 | (func (export "as-compare-last") (param i32) (result i32)
169 | (get_local 0) (get_local 0) (nop) (i32.lt_u)
170 | )
171 | (func (export "as-compare-everywhere") (param i32) (result i32)
172 | (nop) (get_local 0) (nop) (nop) (get_local 0) (nop) (nop) (i32.le_s)
173 | )
174 |
175 | (func (export "as-grow_memory-last") (param i32) (result i32)
176 | (get_local 0) (nop) (grow_memory)
177 | )
178 | (func (export "as-grow_memory-everywhere") (param i32) (result i32)
179 | (nop) (nop) (get_local 0) (nop) (nop) (grow_memory)
180 | )
181 | )
182 |
183 | (assert_return (invoke "as-func-first") (i32.const 1))
184 | (assert_return (invoke "as-func-mid") (i32.const 2))
185 | (assert_return (invoke "as-func-last") (i32.const 3))
186 | (assert_return (invoke "as-func-everywhere") (i32.const 4))
187 |
188 | (assert_return (invoke "as-drop-last" (i32.const 0)))
189 | (assert_return (invoke "as-drop-everywhere" (i32.const 0)))
190 |
191 | (assert_return (invoke "as-select-mid1" (i32.const 3)) (i32.const 3))
192 | (assert_return (invoke "as-select-mid2" (i32.const 3)) (i32.const 3))
193 | (assert_return (invoke "as-select-last" (i32.const 3)) (i32.const 3))
194 | (assert_return (invoke "as-select-everywhere" (i32.const 3)) (i32.const 3))
195 |
196 | (assert_return (invoke "as-block-first") (i32.const 2))
197 | (assert_return (invoke "as-block-mid") (i32.const 2))
198 | (assert_return (invoke "as-block-last") (i32.const 3))
199 | (assert_return (invoke "as-block-everywhere") (i32.const 4))
200 |
201 | (assert_return (invoke "as-loop-first") (i32.const 2))
202 | (assert_return (invoke "as-loop-mid") (i32.const 2))
203 | (assert_return (invoke "as-loop-last") (i32.const 3))
204 | (assert_return (invoke "as-loop-everywhere") (i32.const 4))
205 |
206 | (assert_return (invoke "as-if-condition" (i32.const 0)))
207 | (assert_return (invoke "as-if-condition" (i32.const -1)))
208 | (assert_return (invoke "as-if-then" (i32.const 0)))
209 | (assert_return (invoke "as-if-then" (i32.const 4)))
210 | (assert_return (invoke "as-if-else" (i32.const 0)))
211 | (assert_return (invoke "as-if-else" (i32.const 3)))
212 |
213 | (assert_return (invoke "as-br-last" (i32.const 6)) (i32.const 6))
214 | (assert_return (invoke "as-br-everywhere" (i32.const 7)) (i32.const 7))
215 |
216 | (assert_return (invoke "as-br_if-mid" (i32.const 5)) (i32.const 5))
217 | (assert_return (invoke "as-br_if-last" (i32.const 6)) (i32.const 6))
218 | (assert_return (invoke "as-br_if-everywhere" (i32.const 7)) (i32.const 7))
219 |
220 | (assert_return (invoke "as-br_table-mid" (i32.const 5)) (i32.const 5))
221 | (assert_return (invoke "as-br_table-last" (i32.const 6)) (i32.const 6))
222 | (assert_return (invoke "as-br_table-everywhere" (i32.const 7)) (i32.const 7))
223 |
224 | (assert_return (invoke "as-return-last" (i32.const 6)) (i32.const 6))
225 | (assert_return (invoke "as-return-everywhere" (i32.const 7)) (i32.const 7))
226 |
227 | (assert_return (invoke "as-call-mid1" (i32.const 3) (i32.const 1) (i32.const 2)) (i32.const 2))
228 | (assert_return (invoke "as-call-mid2" (i32.const 0) (i32.const 3) (i32.const 1)) (i32.const 2))
229 | (assert_return (invoke "as-call-last" (i32.const 10) (i32.const 9) (i32.const -1)) (i32.const 20))
230 | (assert_return (invoke "as-call-everywhere" (i32.const 2) (i32.const 1) (i32.const 5)) (i32.const -2))
231 |
232 | (assert_return (invoke "as-unary-last" (i32.const 30)) (i32.const 1))
233 | (assert_return (invoke "as-unary-everywhere" (i32.const 12)) (i32.const 2))
234 |
235 | (assert_return (invoke "as-binary-mid" (i32.const 3)) (i32.const 6))
236 | (assert_return (invoke "as-binary-last" (i32.const 3)) (i32.const 6))
237 | (assert_return (invoke "as-binary-everywhere" (i32.const 3)) (i32.const 6))
238 |
239 | (assert_return (invoke "as-test-last" (i32.const 0)) (i32.const 1))
240 | (assert_return (invoke "as-test-everywhere" (i32.const 0)) (i32.const 1))
241 |
242 | (assert_return (invoke "as-compare-mid" (i32.const 3)) (i32.const 0))
243 | (assert_return (invoke "as-compare-last" (i32.const 3)) (i32.const 0))
244 | (assert_return (invoke "as-compare-everywhere" (i32.const 3)) (i32.const 1))
245 |
246 | (assert_return (invoke "as-grow_memory-last" (i32.const 2)) (i32.const 1))
247 | (assert_return (invoke "as-grow_memory-everywhere" (i32.const 12)) (i32.const 3))
248 |
249 | (assert_invalid
250 | (module (func $type-i32 (result i32) (nop)))
251 | "type mismatch"
252 | )
253 | (assert_invalid
254 | (module (func $type-i64 (result i64) (nop)))
255 | "type mismatch"
256 | )
257 | (assert_invalid
258 | (module (func $type-f32 (result f32) (nop)))
259 | "type mismatch"
260 | )
261 | (assert_invalid
262 | (module (func $type-f64 (result f64) (nop)))
263 | "type mismatch"
264 | )
265 |
--------------------------------------------------------------------------------
/tests/failing/resizing.wast:
--------------------------------------------------------------------------------
1 | (module
2 | (memory 0)
3 |
4 | (func (export "load_at_zero") (result i32) (i32.load (i32.const 0)))
5 | (func (export "store_at_zero") (i32.store (i32.const 0) (i32.const 2)))
6 |
7 | (func (export "load_at_page_size") (result i32) (i32.load (i32.const 0x10000)))
8 | (func (export "store_at_page_size") (i32.store (i32.const 0x10000) (i32.const 3)))
9 |
10 | (func (export "grow") (param $sz i32) (result i32) (grow_memory (get_local $sz)))
11 | (func (export "size") (result i32) (current_memory))
12 | )
13 |
14 | (assert_return (invoke "size") (i32.const 0))
15 | (assert_trap (invoke "store_at_zero") "out of bounds memory access")
16 | (assert_trap (invoke "load_at_zero") "out of bounds memory access")
17 | (assert_trap (invoke "store_at_page_size") "out of bounds memory access")
18 | (assert_trap (invoke "load_at_page_size") "out of bounds memory access")
19 | (assert_return (invoke "grow" (i32.const 1)) (i32.const 0))
20 | (assert_return (invoke "size") (i32.const 1))
21 | (assert_return (invoke "load_at_zero") (i32.const 0))
22 | (assert_return (invoke "store_at_zero"))
23 | (assert_return (invoke "load_at_zero") (i32.const 2))
24 | (assert_trap (invoke "store_at_page_size") "out of bounds memory access")
25 | (assert_trap (invoke "load_at_page_size") "out of bounds memory access")
26 | (assert_return (invoke "grow" (i32.const 4)) (i32.const 1))
27 | (assert_return (invoke "size") (i32.const 5))
28 | (assert_return (invoke "load_at_zero") (i32.const 2))
29 | (assert_return (invoke "store_at_zero"))
30 | (assert_return (invoke "load_at_zero") (i32.const 2))
31 | (assert_return (invoke "load_at_page_size") (i32.const 0))
32 | (assert_return (invoke "store_at_page_size"))
33 | (assert_return (invoke "load_at_page_size") (i32.const 3))
34 |
35 |
36 | (module
37 | (memory 0)
38 | (func (export "grow") (param i32) (result i32) (grow_memory (get_local 0)))
39 | )
40 |
41 | (assert_return (invoke "grow" (i32.const 0)) (i32.const 0))
42 | (assert_return (invoke "grow" (i32.const 1)) (i32.const 0))
43 | (assert_return (invoke "grow" (i32.const 0)) (i32.const 1))
44 | (assert_return (invoke "grow" (i32.const 2)) (i32.const 1))
45 | (assert_return (invoke "grow" (i32.const 800)) (i32.const 3))
46 | (assert_return (invoke "grow" (i32.const 0x10000)) (i32.const -1))
47 |
48 | (module
49 | (memory 0 10)
50 | (func (export "grow") (param i32) (result i32) (grow_memory (get_local 0)))
51 | )
52 |
53 | (assert_return (invoke "grow" (i32.const 0)) (i32.const 0))
54 | (assert_return (invoke "grow" (i32.const 1)) (i32.const 0))
55 | (assert_return (invoke "grow" (i32.const 1)) (i32.const 1))
56 | (assert_return (invoke "grow" (i32.const 2)) (i32.const 2))
57 | (assert_return (invoke "grow" (i32.const 6)) (i32.const 4))
58 | (assert_return (invoke "grow" (i32.const 0)) (i32.const 10))
59 | (assert_return (invoke "grow" (i32.const 1)) (i32.const -1))
60 | (assert_return (invoke "grow" (i32.const 0x10000)) (i32.const -1))
61 |
--------------------------------------------------------------------------------
/tests/failing/select.wast:
--------------------------------------------------------------------------------
1 | (module
2 | (func (export "select_i32") (param $lhs i32) (param $rhs i32) (param $cond i32) (result i32)
3 | (select (get_local $lhs) (get_local $rhs) (get_local $cond)))
4 |
5 | (func (export "select_i64") (param $lhs i64) (param $rhs i64) (param $cond i32) (result i64)
6 | (select (get_local $lhs) (get_local $rhs) (get_local $cond)))
7 |
8 | (func (export "select_f32") (param $lhs f32) (param $rhs f32) (param $cond i32) (result f32)
9 | (select (get_local $lhs) (get_local $rhs) (get_local $cond)))
10 |
11 | (func (export "select_f64") (param $lhs f64) (param $rhs f64) (param $cond i32) (result f64)
12 | (select (get_local $lhs) (get_local $rhs) (get_local $cond)))
13 |
14 | ;; Check that both sides of the select are evaluated
15 | (func (export "select_trap_l") (param $cond i32) (result i32)
16 | (select (unreachable) (i32.const 0) (get_local $cond))
17 | )
18 | (func (export "select_trap_r") (param $cond i32) (result i32)
19 | (select (i32.const 0) (unreachable) (get_local $cond))
20 | )
21 |
22 | (func (export "select_unreached")
23 | (unreachable) (select)
24 | (unreachable) (i32.const 0) (select)
25 | (unreachable) (i32.const 0) (i32.const 0) (select)
26 | (unreachable) (f32.const 0) (i32.const 0) (select)
27 | (unreachable)
28 | )
29 | )
30 |
31 | (assert_return (invoke "select_i32" (i32.const 1) (i32.const 2) (i32.const 1)) (i32.const 1))
32 | (assert_return (invoke "select_i64" (i64.const 2) (i64.const 1) (i32.const 1)) (i64.const 2))
33 | (assert_return (invoke "select_f32" (f32.const 1) (f32.const 2) (i32.const 1)) (f32.const 1))
34 | (assert_return (invoke "select_f64" (f64.const 1) (f64.const 2) (i32.const 1)) (f64.const 1))
35 |
36 | (assert_return (invoke "select_i32" (i32.const 1) (i32.const 2) (i32.const 0)) (i32.const 2))
37 | (assert_return (invoke "select_i32" (i32.const 2) (i32.const 1) (i32.const 0)) (i32.const 1))
38 | (assert_return (invoke "select_i64" (i64.const 2) (i64.const 1) (i32.const -1)) (i64.const 2))
39 | (assert_return (invoke "select_i64" (i64.const 2) (i64.const 1) (i32.const 0xf0f0f0f0)) (i64.const 2))
40 |
41 | (assert_return (invoke "select_f32" (f32.const nan) (f32.const 1) (i32.const 1)) (f32.const nan))
42 | (assert_return (invoke "select_f32" (f32.const nan:0x20304) (f32.const 1) (i32.const 1)) (f32.const nan:0x20304))
43 | (assert_return (invoke "select_f32" (f32.const nan) (f32.const 1) (i32.const 0)) (f32.const 1))
44 | (assert_return (invoke "select_f32" (f32.const nan:0x20304) (f32.const 1) (i32.const 0)) (f32.const 1))
45 | (assert_return (invoke "select_f32" (f32.const 2) (f32.const nan) (i32.const 1)) (f32.const 2))
46 | (assert_return (invoke "select_f32" (f32.const 2) (f32.const nan:0x20304) (i32.const 1)) (f32.const 2))
47 | (assert_return (invoke "select_f32" (f32.const 2) (f32.const nan) (i32.const 0)) (f32.const nan))
48 | (assert_return (invoke "select_f32" (f32.const 2) (f32.const nan:0x20304) (i32.const 0)) (f32.const nan:0x20304))
49 |
50 | (assert_return (invoke "select_f64" (f64.const nan) (f64.const 1) (i32.const 1)) (f64.const nan))
51 | (assert_return (invoke "select_f64" (f64.const nan:0x20304) (f64.const 1) (i32.const 1)) (f64.const nan:0x20304))
52 | (assert_return (invoke "select_f64" (f64.const nan) (f64.const 1) (i32.const 0)) (f64.const 1))
53 | (assert_return (invoke "select_f64" (f64.const nan:0x20304) (f64.const 1) (i32.const 0)) (f64.const 1))
54 | (assert_return (invoke "select_f64" (f64.const 2) (f64.const nan) (i32.const 1)) (f64.const 2))
55 | (assert_return (invoke "select_f64" (f64.const 2) (f64.const nan:0x20304) (i32.const 1)) (f64.const 2))
56 | (assert_return (invoke "select_f64" (f64.const 2) (f64.const nan) (i32.const 0)) (f64.const nan))
57 | (assert_return (invoke "select_f64" (f64.const 2) (f64.const nan:0x20304) (i32.const 0)) (f64.const nan:0x20304))
58 |
59 | (assert_trap (invoke "select_trap_l" (i32.const 1)) "unreachable executed")
60 | (assert_trap (invoke "select_trap_l" (i32.const 0)) "unreachable executed")
61 | (assert_trap (invoke "select_trap_r" (i32.const 1)) "unreachable executed")
62 | (assert_trap (invoke "select_trap_r" (i32.const 0)) "unreachable executed")
63 |
64 | (assert_invalid
65 | (module (func $arity-0 (select (nop) (nop) (i32.const 1))))
66 | "type mismatch"
67 | )
68 |
--------------------------------------------------------------------------------
/tests/failing/set_local.wast:
--------------------------------------------------------------------------------
1 | ;; Test `set_local` operator
2 |
3 | (module
4 | ;; Typing
5 |
6 | (func (export "type-local-i32") (local i32) (set_local 0 (i32.const 0)))
7 | (func (export "type-local-i64") (local i64) (set_local 0 (i64.const 0)))
8 | (func (export "type-local-f32") (local f32) (set_local 0 (f32.const 0)))
9 | (func (export "type-local-f64") (local f64) (set_local 0 (f64.const 0)))
10 |
11 | (func (export "type-param-i32") (param i32) (set_local 0 (i32.const 10)))
12 | (func (export "type-param-i64") (param i64) (set_local 0 (i64.const 11)))
13 | (func (export "type-param-f32") (param f32) (set_local 0 (f32.const 11.1)))
14 | (func (export "type-param-f64") (param f64) (set_local 0 (f64.const 12.2)))
15 |
16 | (func (export "type-mixed") (param i64 f32 f64 i32 i32) (local f32 i64 i64 f64)
17 | (set_local 0 (i64.const 0))
18 | (set_local 1 (f32.const 0))
19 | (set_local 2 (f64.const 0))
20 | (set_local 3 (i32.const 0))
21 | (set_local 4 (i32.const 0))
22 | (set_local 5 (f32.const 0))
23 | (set_local 6 (i64.const 0))
24 | (set_local 7 (i64.const 0))
25 | (set_local 8 (f64.const 0))
26 | )
27 |
28 | ;; Writing
29 |
30 | (func (export "write") (param i64 f32 f64 i32 i32) (result i64)
31 | (local f32 i64 i64 f64)
32 | (set_local 1 (f32.const -0.3))
33 | (set_local 3 (i32.const 40))
34 | (set_local 4 (i32.const -7))
35 | (set_local 5 (f32.const 5.5))
36 | (set_local 6 (i64.const 6))
37 | (set_local 8 (f64.const 8))
38 | (i64.trunc_s/f64
39 | (f64.add
40 | (f64.convert_u/i64 (get_local 0))
41 | (f64.add
42 | (f64.promote/f32 (get_local 1))
43 | (f64.add
44 | (get_local 2)
45 | (f64.add
46 | (f64.convert_u/i32 (get_local 3))
47 | (f64.add
48 | (f64.convert_s/i32 (get_local 4))
49 | (f64.add
50 | (f64.promote/f32 (get_local 5))
51 | (f64.add
52 | (f64.convert_u/i64 (get_local 6))
53 | (f64.add
54 | (f64.convert_u/i64 (get_local 7))
55 | (get_local 8)
56 | )
57 | )
58 | )
59 | )
60 | )
61 | )
62 | )
63 | )
64 | )
65 | )
66 | )
67 |
68 | (assert_return (invoke "type-local-i32"))
69 | (assert_return (invoke "type-local-i64"))
70 | (assert_return (invoke "type-local-f32"))
71 | (assert_return (invoke "type-local-f64"))
72 |
73 | (assert_return (invoke "type-param-i32" (i32.const 2)))
74 | (assert_return (invoke "type-param-i64" (i64.const 3)))
75 | (assert_return (invoke "type-param-f32" (f32.const 4.4)))
76 | (assert_return (invoke "type-param-f64" (f64.const 5.5)))
77 |
78 | (assert_return
79 | (invoke "type-mixed"
80 | (i64.const 1) (f32.const 2.2) (f64.const 3.3) (i32.const 4) (i32.const 5)
81 | )
82 | )
83 |
84 | (assert_return
85 | (invoke "write"
86 | (i64.const 1) (f32.const 2) (f64.const 3.3) (i32.const 4) (i32.const 5)
87 | )
88 | (i64.const 56)
89 | )
90 |
91 |
92 | ;; Invalid typing of access to locals
93 |
94 | (assert_invalid
95 | (module (func $type-local-num-vs-num (result i64) (local i32)
96 | (set_local 0 (i32.const 0))
97 | ))
98 | "type mismatch"
99 | )
100 | (assert_invalid
101 | (module (func $type-local-num-vs-num (local f32)
102 | (i32.eqz (set_local 0 (f32.const 0)))
103 | ))
104 | "type mismatch"
105 | )
106 | (assert_invalid
107 | (module (func $type-local-num-vs-num (local f64 i64)
108 | (f64.neg (set_local 1 (i64.const 0)))
109 | ))
110 | "type mismatch"
111 | )
112 |
113 | (assert_invalid
114 | (module (func $type-local-arg-void-vs-num (local i32) (set_local 0 (nop))))
115 | "type mismatch"
116 | )
117 | (assert_invalid
118 | (module (func $type-local-arg-num-vs-num (local i32) (set_local 0 (f32.const 0))))
119 | "type mismatch"
120 | )
121 | (assert_invalid
122 | (module (func $type-local-arg-num-vs-num (local f32) (set_local 0 (f64.const 0))))
123 | "type mismatch"
124 | )
125 | (assert_invalid
126 | (module (func $type-local-arg-num-vs-num (local f64 i64) (set_local 1 (f64.const 0))))
127 | "type mismatch"
128 | )
129 |
130 |
131 | ;; Invalid typing of access to parameters
132 |
133 | (assert_invalid
134 | (module (func $type-param-num-vs-num (param i32) (result i64) (get_local 0)))
135 | "type mismatch"
136 | )
137 | (assert_invalid
138 | (module (func $type-param-num-vs-num (param f32) (i32.eqz (get_local 0))))
139 | "type mismatch"
140 | )
141 | (assert_invalid
142 | (module (func $type-param-num-vs-num (param f64 i64) (f64.neg (get_local 1))))
143 | "type mismatch"
144 | )
145 |
146 | (assert_invalid
147 | (module (func $type-param-arg-void-vs-num (param i32) (set_local 0 (nop))))
148 | "type mismatch"
149 | )
150 | (assert_invalid
151 | (module (func $type-param-arg-num-vs-num (param i32) (set_local 0 (f32.const 0))))
152 | "type mismatch"
153 | )
154 | (assert_invalid
155 | (module (func $type-param-arg-num-vs-num (param f32) (set_local 0 (f64.const 0))))
156 | "type mismatch"
157 | )
158 | (assert_invalid
159 | (module (func $type-param-arg-num-vs-num (param f64 i64) (set_local 1 (f64.const 0))))
160 | "type mismatch"
161 | )
162 |
163 |
164 | ;; Invalid local index
165 |
166 | (assert_invalid
167 | (module (func $unbound-local (local i32 i64) (get_local 3)))
168 | "unknown local"
169 | )
170 | (assert_invalid
171 | (module (func $large-local (local i32 i64) (get_local 14324343)))
172 | "unknown local"
173 | )
174 |
175 | (assert_invalid
176 | (module (func $unbound-param (param i32 i64) (get_local 2)))
177 | "unknown local"
178 | )
179 | (assert_invalid
180 | (module (func $large-param (local i32 i64) (get_local 714324343)))
181 | "unknown local"
182 | )
183 |
184 | (assert_invalid
185 | (module (func $unbound-mixed (param i32) (local i32 i64) (get_local 3)))
186 | "unknown local"
187 | )
188 | (assert_invalid
189 | (module (func $large-mixed (param i64) (local i32 i64) (get_local 214324343)))
190 | "unknown local"
191 | )
192 |
193 | (assert_invalid
194 | (module (func $type-mixed-arg-num-vs-num (param f32) (local i32) (set_local 1 (f32.const 0))))
195 | "type mismatch"
196 | )
197 | (assert_invalid
198 | (module (func $type-mixed-arg-num-vs-num (param i64 i32) (local f32) (set_local 1 (f32.const 0))))
199 | "type mismatch"
200 | )
201 | (assert_invalid
202 | (module (func $type-mixed-arg-num-vs-num (param i64) (local f64 i64) (set_local 1 (i64.const 0))))
203 | "type mismatch"
204 | )
205 |
206 |
--------------------------------------------------------------------------------
/tests/failing/simple.wast.golden.wasm:
--------------------------------------------------------------------------------
1 | asm
--------------------------------------------------------------------------------
/tests/failing/simple.wast.out.wasm:
--------------------------------------------------------------------------------
1 | asm
--------------------------------------------------------------------------------
/tests/failing/stack.wast:
--------------------------------------------------------------------------------
1 | (module
2 | (func (export "fac-expr") (param $n i64) (result i64)
3 | (local $i i64)
4 | (local $res i64)
5 | (set_local $i (get_local $n))
6 | (set_local $res (i64.const 1))
7 | (block $done
8 | (loop $loop
9 | (if
10 | (i64.eq (get_local $i) (i64.const 0))
11 | (then (br $done))
12 | (else
13 | (set_local $res (i64.mul (get_local $i) (get_local $res)))
14 | (set_local $i (i64.sub (get_local $i) (i64.const 1)))
15 | )
16 | )
17 | (br $loop)
18 | )
19 | )
20 | (get_local $res)
21 | )
22 |
23 | (func (export "fac-stack") (param $n i64) (result i64)
24 | (local $i i64)
25 | (local $res i64)
26 | (get_local $n)
27 | (set_local $i)
28 | (i64.const 1)
29 | (set_local $res)
30 | (block $done
31 | (loop $loop
32 | (get_local $i)
33 | (i64.const 0)
34 | (i64.eq)
35 | (if
36 | (then (br $done))
37 | (else
38 | (get_local $i)
39 | (get_local $res)
40 | (i64.mul)
41 | (set_local $res)
42 | (get_local $i)
43 | (i64.const 1)
44 | (i64.sub)
45 | (set_local $i)
46 | )
47 | )
48 | (br $loop)
49 | )
50 | )
51 | (get_local $res)
52 | )
53 |
54 | (func (export "fac-stack-raw") (param $n i64) (result i64)
55 | (local $i i64)
56 | (local $res i64)
57 | get_local $n
58 | set_local $i
59 | i64.const 1
60 | set_local $res
61 | block $done
62 | loop $loop
63 | get_local $i
64 | i64.const 0
65 | i64.eq
66 | if $body
67 | br $done
68 | else $body
69 | get_local $i
70 | get_local $res
71 | i64.mul
72 | set_local $res
73 | get_local $i
74 | i64.const 1
75 | i64.sub
76 | set_local $i
77 | end $body
78 | br $loop
79 | end $loop
80 | end $done
81 | get_local $res
82 | )
83 |
84 | (func (export "fac-mixed") (param $n i64) (result i64)
85 | (local $i i64)
86 | (local $res i64)
87 | (set_local $i (get_local $n))
88 | (set_local $res (i64.const 1))
89 | (block $done
90 | (loop $loop
91 | (i64.eq (get_local $i) (i64.const 0))
92 | (if
93 | (then (br $done))
94 | (else
95 | (i64.mul (get_local $i) (get_local $res))
96 | (set_local $res)
97 | (i64.sub (get_local $i) (i64.const 1))
98 | (set_local $i)
99 | )
100 | )
101 | (br $loop)
102 | )
103 | )
104 | (get_local $res)
105 | )
106 |
107 | (func (export "fac-mixed-raw") (param $n i64) (result i64)
108 | (local $i i64)
109 | (local $res i64)
110 | (set_local $i (get_local $n))
111 | (set_local $res (i64.const 1))
112 | block $done
113 | loop $loop
114 | (i64.eq (get_local $i) (i64.const 0))
115 | if
116 | br $done
117 | else
118 | (i64.mul (get_local $i) (get_local $res))
119 | set_local $res
120 | (i64.sub (get_local $i) (i64.const 1))
121 | set_local $i
122 | end
123 | br $loop
124 | end
125 | end
126 | get_local $res
127 | )
128 | )
129 |
130 | (assert_return (invoke "fac-expr" (i64.const 25)) (i64.const 7034535277573963776))
131 | (assert_return (invoke "fac-stack" (i64.const 25)) (i64.const 7034535277573963776))
132 | (assert_return (invoke "fac-mixed" (i64.const 25)) (i64.const 7034535277573963776))
133 |
--------------------------------------------------------------------------------
/tests/failing/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") (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") (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 |
--------------------------------------------------------------------------------
/tests/failing/store_retval.wast:
--------------------------------------------------------------------------------
1 | (assert_invalid
2 | (module (func (param i32) (result i32) (set_local 0 (i32.const 1))))
3 | "type mismatch"
4 | )
5 | (assert_invalid
6 | (module (func (param i64) (result i64) (set_local 0 (i64.const 1))))
7 | "type mismatch"
8 | )
9 | (assert_invalid
10 | (module (func (param f32) (result f32) (set_local 0 (f32.const 1))))
11 | "type mismatch"
12 | )
13 | (assert_invalid
14 | (module (func (param f64) (result f64) (set_local 0 (f64.const 1))))
15 | "type mismatch"
16 | )
17 |
18 | (assert_invalid
19 | (module (memory 1) (func (param i32) (result i32) (i32.store (i32.const 0) (i32.const 1))))
20 | "type mismatch"
21 | )
22 | (assert_invalid
23 | (module (memory 1) (func (param i64) (result i64) (i64.store (i32.const 0) (i64.const 1))))
24 | "type mismatch"
25 | )
26 | (assert_invalid
27 | (module (memory 1) (func (param f32) (result f32) (f32.store (i32.const 0) (f32.const 1))))
28 | "type mismatch"
29 | )
30 | (assert_invalid
31 | (module (memory 1) (func (param f64) (result f64) (f64.store (i32.const 0) (f64.const 1))))
32 | "type mismatch"
33 | )
34 |
35 | (assert_invalid
36 | (module (memory 1) (func (param i32) (result i32) (i32.store8 (i32.const 0) (i32.const 1))))
37 | "type mismatch"
38 | )
39 | (assert_invalid
40 | (module (memory 1) (func (param i32) (result i32) (i32.store16 (i32.const 0) (i32.const 1))))
41 | "type mismatch"
42 | )
43 | (assert_invalid
44 | (module (memory 1) (func (param i64) (result i64) (i64.store8 (i32.const 0) (i64.const 1))))
45 | "type mismatch"
46 | )
47 | (assert_invalid
48 | (module (memory 1) (func (param i64) (result i64) (i64.store16 (i32.const 0) (i64.const 1))))
49 | "type mismatch"
50 | )
51 | (assert_invalid
52 | (module (memory 1) (func (param i64) (result i64) (i64.store32 (i32.const 0) (i64.const 1))))
53 | "type mismatch"
54 | )
55 |
56 |
--------------------------------------------------------------------------------
/tests/failing/switch.wast:
--------------------------------------------------------------------------------
1 | (module
2 | ;; Statement switch
3 | (func (export "stmt") (param $i i32) (result i32)
4 | (local $j i32)
5 | (set_local $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 | (get_local $i)
18 | )
19 | ) ;; 0
20 | (return (get_local $i))
21 | ) ;; 1
22 | (nop)
23 | ;; fallthrough
24 | ) ;; 2
25 | ;; fallthrough
26 | ) ;; 3
27 | (set_local $j (i32.sub (i32.const 0) (get_local $i)))
28 | (br $switch)
29 | ) ;; 4
30 | (br $switch)
31 | ) ;; 5
32 | (set_local $j (i32.const 101))
33 | (br $switch)
34 | ) ;; 6
35 | (set_local $j (i32.const 101))
36 | ;; fallthrough
37 | ) ;; default
38 | (set_local $j (i32.const 102))
39 | ) ;; 7
40 | ;; fallthrough
41 | )
42 | (return (get_local $j))
43 | )
44 |
45 | ;; Expression switch
46 | (func (export "expr") (param $i i64) (result i64)
47 | (local $j i64)
48 | (set_local $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 (get_local $i))
62 | )
63 | ) ;; 0
64 | (return (get_local $i))
65 | ) ;; 1
66 | (nop)
67 | ;; fallthrough
68 | ) ;; 2
69 | ;; fallthrough
70 | ) ;; 3
71 | (br $switch (i64.sub (i64.const 0) (get_local $i)))
72 | ) ;; 6
73 | (set_local $j (i64.const 101))
74 | ;; fallthrough
75 | ) ;; 4
76 | ;; fallthrough
77 | ) ;; 5
78 | ;; fallthrough
79 | ) ;; default
80 | (br $switch (get_local $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) (get_local $i))
99 | (i32.and (i32.const 3) (get_local $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 |
--------------------------------------------------------------------------------
/tests/failing/tee_local.wast:
--------------------------------------------------------------------------------
1 | ;; Test `tee_local` operator
2 |
3 | (module
4 | ;; Typing
5 |
6 | (func (export "type-local-i32") (result i32) (local i32) (tee_local 0 (i32.const 0)))
7 | (func (export "type-local-i64") (result i64) (local i64) (tee_local 0 (i64.const 0)))
8 | (func (export "type-local-f32") (result f32) (local f32) (tee_local 0 (f32.const 0)))
9 | (func (export "type-local-f64") (result f64) (local f64) (tee_local 0 (f64.const 0)))
10 |
11 | (func (export "type-param-i32") (param i32) (result i32) (tee_local 0 (i32.const 10)))
12 | (func (export "type-param-i64") (param i64) (result i64) (tee_local 0 (i64.const 11)))
13 | (func (export "type-param-f32") (param f32) (result f32) (tee_local 0 (f32.const 11.1)))
14 | (func (export "type-param-f64") (param f64) (result f64) (tee_local 0 (f64.const 12.2)))
15 |
16 | (func (export "type-mixed") (param i64 f32 f64 i32 i32) (local f32 i64 i64 f64)
17 | (drop (i64.eqz (tee_local 0 (i64.const 0))))
18 | (drop (f32.neg (tee_local 1 (f32.const 0))))
19 | (drop (f64.neg (tee_local 2 (f64.const 0))))
20 | (drop (i32.eqz (tee_local 3 (i32.const 0))))
21 | (drop (i32.eqz (tee_local 4 (i32.const 0))))
22 | (drop (f32.neg (tee_local 5 (f32.const 0))))
23 | (drop (i64.eqz (tee_local 6 (i64.const 0))))
24 | (drop (i64.eqz (tee_local 7 (i64.const 0))))
25 | (drop (f64.neg (tee_local 8 (f64.const 0))))
26 | )
27 |
28 | ;; Writing
29 |
30 | (func (export "write") (param i64 f32 f64 i32 i32) (result i64) (local f32 i64 i64 f64)
31 | (drop (tee_local 1 (f32.const -0.3)))
32 | (drop (tee_local 3 (i32.const 40)))
33 | (drop (tee_local 4 (i32.const -7)))
34 | (drop (tee_local 5 (f32.const 5.5)))
35 | (drop (tee_local 6 (i64.const 6)))
36 | (drop (tee_local 8 (f64.const 8)))
37 | (i64.trunc_s/f64
38 | (f64.add
39 | (f64.convert_u/i64 (get_local 0))
40 | (f64.add
41 | (f64.promote/f32 (get_local 1))
42 | (f64.add
43 | (get_local 2)
44 | (f64.add
45 | (f64.convert_u/i32 (get_local 3))
46 | (f64.add
47 | (f64.convert_s/i32 (get_local 4))
48 | (f64.add
49 | (f64.promote/f32 (get_local 5))
50 | (f64.add
51 | (f64.convert_u/i64 (get_local 6))
52 | (f64.add
53 | (f64.convert_u/i64 (get_local 7))
54 | (get_local 8)
55 | )
56 | )
57 | )
58 | )
59 | )
60 | )
61 | )
62 | )
63 | )
64 | )
65 |
66 | ;; Result
67 |
68 | (func (export "result") (param i64 f32 f64 i32 i32) (result f64)
69 | (local f32 i64 i64 f64)
70 | (f64.add
71 | (f64.convert_u/i64 (tee_local 0 (i64.const 1)))
72 | (f64.add
73 | (f64.promote/f32 (tee_local 1 (f32.const 2)))
74 | (f64.add
75 | (tee_local 2 (f64.const 3.3))
76 | (f64.add
77 | (f64.convert_u/i32 (tee_local 3 (i32.const 4)))
78 | (f64.add
79 | (f64.convert_s/i32 (tee_local 4 (i32.const 5)))
80 | (f64.add
81 | (f64.promote/f32 (tee_local 5 (f32.const 5.5)))
82 | (f64.add
83 | (f64.convert_u/i64 (tee_local 6 (i64.const 6)))
84 | (f64.add
85 | (f64.convert_u/i64 (tee_local 7 (i64.const 0)))
86 | (tee_local 8 (f64.const 8))
87 | )
88 | )
89 | )
90 | )
91 | )
92 | )
93 | )
94 | )
95 | )
96 | )
97 |
98 | (assert_return (invoke "type-local-i32") (i32.const 0))
99 | (assert_return (invoke "type-local-i64") (i64.const 0))
100 | (assert_return (invoke "type-local-f32") (f32.const 0))
101 | (assert_return (invoke "type-local-f64") (f64.const 0))
102 |
103 | (assert_return (invoke "type-param-i32" (i32.const 2)) (i32.const 10))
104 | (assert_return (invoke "type-param-i64" (i64.const 3)) (i64.const 11))
105 | (assert_return (invoke "type-param-f32" (f32.const 4.4)) (f32.const 11.1))
106 | (assert_return (invoke "type-param-f64" (f64.const 5.5)) (f64.const 12.2))
107 |
108 | (assert_return
109 | (invoke "type-mixed"
110 | (i64.const 1) (f32.const 2.2) (f64.const 3.3) (i32.const 4) (i32.const 5)
111 | )
112 | )
113 |
114 | (assert_return
115 | (invoke "write"
116 | (i64.const 1) (f32.const 2) (f64.const 3.3) (i32.const 4) (i32.const 5)
117 | )
118 | (i64.const 56)
119 | )
120 |
121 | (assert_return
122 | (invoke "result"
123 | (i64.const -1) (f32.const -2) (f64.const -3.3) (i32.const -4) (i32.const -5)
124 | )
125 | (f64.const 34.8)
126 | )
127 |
128 |
129 | ;; Invalid typing of access to locals
130 |
131 | (assert_invalid
132 | (module (func $type-local-num-vs-num (result i64) (local i32) (tee_local 0 (i32.const 0))))
133 | "type mismatch"
134 | )
135 | (assert_invalid
136 | (module (func $type-local-num-vs-num (local f32) (i32.eqz (tee_local 0 (f32.const 0)))))
137 | "type mismatch"
138 | )
139 | (assert_invalid
140 | (module (func $type-local-num-vs-num (local f64 i64) (f64.neg (tee_local 1 (i64.const 0)))))
141 | "type mismatch"
142 | )
143 |
144 | (assert_invalid
145 | (module (func $type-local-arg-void-vs-num (local i32) (tee_local 0 (nop))))
146 | "type mismatch"
147 | )
148 | (assert_invalid
149 | (module (func $type-local-arg-num-vs-num (local i32) (tee_local 0 (f32.const 0))))
150 | "type mismatch"
151 | )
152 | (assert_invalid
153 | (module (func $type-local-arg-num-vs-num (local f32) (tee_local 0 (f64.const 0))))
154 | "type mismatch"
155 | )
156 | (assert_invalid
157 | (module (func $type-local-arg-num-vs-num (local f64 i64) (tee_local 1 (f64.const 0))))
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) (get_local 0)))
166 | "type mismatch"
167 | )
168 | (assert_invalid
169 | (module (func $type-param-num-vs-num (param f32) (i32.eqz (get_local 0))))
170 | "type mismatch"
171 | )
172 | (assert_invalid
173 | (module (func $type-param-num-vs-num (param f64 i64) (f64.neg (get_local 1))))
174 | "type mismatch"
175 | )
176 |
177 | (assert_invalid
178 | (module (func $type-param-arg-void-vs-num (param i32) (tee_local 0 (nop))))
179 | "type mismatch"
180 | )
181 | (assert_invalid
182 | (module (func $type-param-arg-num-vs-num (param i32) (tee_local 0 (f32.const 0))))
183 | "type mismatch"
184 | )
185 | (assert_invalid
186 | (module (func $type-param-arg-num-vs-num (param f32) (tee_local 0 (f64.const 0))))
187 | "type mismatch"
188 | )
189 | (assert_invalid
190 | (module (func $type-param-arg-num-vs-num (param f64 i64) (tee_local 1 (f64.const 0))))
191 | "type mismatch"
192 | )
193 |
194 |
195 | ;; Invalid local index
196 |
197 | (assert_invalid
198 | (module (func $unbound-local (local i32 i64) (get_local 3)))
199 | "unknown local"
200 | )
201 | (assert_invalid
202 | (module (func $large-local (local i32 i64) (get_local 14324343)))
203 | "unknown local"
204 | )
205 |
206 | (assert_invalid
207 | (module (func $unbound-param (param i32 i64) (get_local 2)))
208 | "unknown local"
209 | )
210 | (assert_invalid
211 | (module (func $large-param (local i32 i64) (get_local 714324343)))
212 | "unknown local"
213 | )
214 |
215 | (assert_invalid
216 | (module (func $unbound-mixed (param i32) (local i32 i64) (get_local 3)))
217 | "unknown local"
218 | )
219 | (assert_invalid
220 | (module (func $large-mixed (param i64) (local i32 i64) (get_local 214324343)))
221 | "unknown local"
222 | )
223 |
224 | (assert_invalid
225 | (module (func $type-mixed-arg-num-vs-num (param f32) (local i32) (tee_local 1 (f32.const 0))))
226 | "type mismatch"
227 | )
228 | (assert_invalid
229 | (module (func $type-mixed-arg-num-vs-num (param i64 i32) (local f32) (tee_local 1 (f32.const 0))))
230 | "type mismatch"
231 | )
232 | (assert_invalid
233 | (module (func $type-mixed-arg-num-vs-num (param i64) (local f64 i64) (tee_local 1 (i64.const 0))))
234 | "type mismatch"
235 | )
236 |
237 |
--------------------------------------------------------------------------------
/tests/failing/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 |
--------------------------------------------------------------------------------
/tests/failing/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 (get_local $x) (get_local $y))))
8 | (func (export "no_dce.i32.div_u") (param $x i32) (param $y i32)
9 | (drop (i32.div_u (get_local $x) (get_local $y))))
10 | (func (export "no_dce.i64.div_s") (param $x i64) (param $y i64)
11 | (drop (i64.div_s (get_local $x) (get_local $y))))
12 | (func (export "no_dce.i64.div_u") (param $x i64) (param $y i64)
13 | (drop (i64.div_u (get_local $x) (get_local $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 (get_local $x) (get_local $y))))
26 | (func (export "no_dce.i32.rem_u") (param $x i32) (param $y i32)
27 | (drop (i32.rem_u (get_local $x) (get_local $y))))
28 | (func (export "no_dce.i64.rem_s") (param $x i64) (param $y i64)
29 | (drop (i64.rem_s (get_local $x) (get_local $y))))
30 | (func (export "no_dce.i64.rem_u") (param $x i64) (param $y i64)
31 | (drop (i64.rem_u (get_local $x) (get_local $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_s_f32") (param $x f32) (drop (i32.trunc_s/f32 (get_local $x))))
41 | (func (export "no_dce.i32.trunc_u_f32") (param $x f32) (drop (i32.trunc_u/f32 (get_local $x))))
42 | (func (export "no_dce.i32.trunc_s_f64") (param $x f64) (drop (i32.trunc_s/f64 (get_local $x))))
43 | (func (export "no_dce.i32.trunc_u_f64") (param $x f64) (drop (i32.trunc_u/f64 (get_local $x))))
44 | (func (export "no_dce.i64.trunc_s_f32") (param $x f32) (drop (i64.trunc_s/f32 (get_local $x))))
45 | (func (export "no_dce.i64.trunc_u_f32") (param $x f32) (drop (i64.trunc_u/f32 (get_local $x))))
46 | (func (export "no_dce.i64.trunc_s_f64") (param $x f64) (drop (i64.trunc_s/f64 (get_local $x))))
47 | (func (export "no_dce.i64.trunc_u_f64") (param $x f64) (drop (i64.trunc_u/f64 (get_local $x))))
48 | )
49 |
50 | (assert_trap (invoke "no_dce.i32.trunc_s_f32" (f32.const nan)) "invalid conversion to integer")
51 | (assert_trap (invoke "no_dce.i32.trunc_u_f32" (f32.const nan)) "invalid conversion to integer")
52 | (assert_trap (invoke "no_dce.i32.trunc_s_f64" (f64.const nan)) "invalid conversion to integer")
53 | (assert_trap (invoke "no_dce.i32.trunc_u_f64" (f64.const nan)) "invalid conversion to integer")
54 | (assert_trap (invoke "no_dce.i64.trunc_s_f32" (f32.const nan)) "invalid conversion to integer")
55 | (assert_trap (invoke "no_dce.i64.trunc_u_f32" (f32.const nan)) "invalid conversion to integer")
56 | (assert_trap (invoke "no_dce.i64.trunc_s_f64" (f64.const nan)) "invalid conversion to integer")
57 | (assert_trap (invoke "no_dce.i64.trunc_u_f64" (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 (get_local $i))))
63 | (func (export "no_dce.i32.load16_s") (param $i i32) (drop (i32.load16_s (get_local $i))))
64 | (func (export "no_dce.i32.load16_u") (param $i i32) (drop (i32.load16_u (get_local $i))))
65 | (func (export "no_dce.i32.load8_s") (param $i i32) (drop (i32.load8_s (get_local $i))))
66 | (func (export "no_dce.i32.load8_u") (param $i i32) (drop (i32.load8_u (get_local $i))))
67 | (func (export "no_dce.i64.load") (param $i i32) (drop (i64.load (get_local $i))))
68 | (func (export "no_dce.i64.load32_s") (param $i i32) (drop (i64.load32_s (get_local $i))))
69 | (func (export "no_dce.i64.load32_u") (param $i i32) (drop (i64.load32_u (get_local $i))))
70 | (func (export "no_dce.i64.load16_s") (param $i i32) (drop (i64.load16_s (get_local $i))))
71 | (func (export "no_dce.i64.load16_u") (param $i i32) (drop (i64.load16_u (get_local $i))))
72 | (func (export "no_dce.i64.load8_s") (param $i i32) (drop (i64.load8_s (get_local $i))))
73 | (func (export "no_dce.i64.load8_u") (param $i i32) (drop (i64.load8_u (get_local $i))))
74 | (func (export "no_dce.f32.load") (param $i i32) (drop (f32.load (get_local $i))))
75 | (func (export "no_dce.f64.load") (param $i i32) (drop (f64.load (get_local $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 |
--------------------------------------------------------------------------------
/tests/failing/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 | "result before parameter"
46 | )
47 | (assert_malformed
48 | (module quote "(type (func (result $x i32)))")
49 | "unexpected token"
50 | )
51 |
52 | (assert_invalid
53 | (module (type (func (result i32 i32))))
54 | "invalid result arity"
55 | )
56 | (assert_invalid
57 | (module (type (func (result i32) (result i32))))
58 | "invalid result arity"
59 | )
60 |
--------------------------------------------------------------------------------
/tests/failing/unreachable.wast:
--------------------------------------------------------------------------------
1 | ;; Test `unreachable` operator
2 |
3 | (module
4 | ;; Auxiliary definitions
5 | (func $dummy)
6 | (func $dummy3 (param i32 i32 i32))
7 |
8 | (func (export "type-i32") (result i32) (unreachable))
9 | (func (export "type-i64") (result i32) (unreachable))
10 | (func (export "type-f32") (result f64) (unreachable))
11 | (func (export "type-f64") (result f64) (unreachable))
12 |
13 | (func (export "as-func-first") (result i32)
14 | (unreachable) (i32.const -1)
15 | )
16 | (func (export "as-func-mid") (result i32)
17 | (call $dummy) (unreachable) (i32.const -1)
18 | )
19 | (func (export "as-func-last")
20 | (call $dummy) (unreachable)
21 | )
22 | (func (export "as-func-value") (result i32)
23 | (call $dummy) (unreachable)
24 | )
25 |
26 | (func (export "as-block-first") (result i32)
27 | (block (result i32) (unreachable) (i32.const 2))
28 | )
29 | (func (export "as-block-mid") (result i32)
30 | (block (result i32) (call $dummy) (unreachable) (i32.const 2))
31 | )
32 | (func (export "as-block-last")
33 | (block (nop) (call $dummy) (unreachable))
34 | )
35 | (func (export "as-block-value") (result i32)
36 | (block (result i32) (nop) (call $dummy) (unreachable))
37 | )
38 | (func (export "as-block-broke") (result i32)
39 | (block (result i32) (call $dummy) (br 0 (i32.const 1)) (unreachable))
40 | )
41 |
42 | (func (export "as-loop-first") (result i32)
43 | (loop (result i32) (unreachable) (i32.const 2))
44 | )
45 | (func (export "as-loop-mid") (result i32)
46 | (loop (result i32) (call $dummy) (unreachable) (i32.const 2))
47 | )
48 | (func (export "as-loop-last")
49 | (loop (nop) (call $dummy) (unreachable))
50 | )
51 | (func (export "as-loop-broke") (result i32)
52 | (block (result i32)
53 | (loop (result i32) (call $dummy) (br 1 (i32.const 1)) (unreachable))
54 | )
55 | )
56 |
57 | (func (export "as-br-value") (result i32)
58 | (block (result i32) (br 0 (unreachable)))
59 | )
60 |
61 | (func (export "as-br_if-cond")
62 | (block (br_if 0 (unreachable)))
63 | )
64 | (func (export "as-br_if-value") (result i32)
65 | (block (result i32)
66 | (drop (br_if 0 (unreachable) (i32.const 1))) (i32.const 7)
67 | )
68 | )
69 | (func (export "as-br_if-value-cond") (result i32)
70 | (block (result i32)
71 | (drop (br_if 0 (i32.const 6) (unreachable))) (i32.const 7)
72 | )
73 | )
74 |
75 | (func (export "as-br_table-index")
76 | (block (br_table 0 0 0 (unreachable)))
77 | )
78 | (func (export "as-br_table-value") (result i32)
79 | (block (result i32)
80 | (br_table 0 0 0 (unreachable) (i32.const 1)) (i32.const 7)
81 | )
82 | )
83 | (func (export "as-br_table-value-2") (result i32)
84 | (block (result i32)
85 | (block (result i32) (br_table 0 1 (unreachable) (i32.const 1)))
86 | )
87 | )
88 | (func (export "as-br_table-value-index") (result i32)
89 | (block (result i32)
90 | (br_table 0 0 (i32.const 6) (unreachable)) (i32.const 7)
91 | )
92 | )
93 | (func (export "as-br_table-value-and-index") (result i32)
94 | (block (result i32) (br_table 0 0 (unreachable)) (i32.const 8))
95 | )
96 |
97 | (func (export "as-return-value") (result i64)
98 | (return (unreachable))
99 | )
100 |
101 | (func (export "as-if-cond") (result i32)
102 | (if (result i32) (unreachable) (then (i32.const 0)) (else (i32.const 1)))
103 | )
104 | (func (export "as-if-then") (param i32 i32) (result i32)
105 | (if (result i32) (get_local 0) (then (unreachable)) (else (get_local 1)))
106 | )
107 | (func (export "as-if-else") (param i32 i32) (result i32)
108 | (if (result i32) (get_local 0) (then (get_local 1)) (else (unreachable)))
109 | )
110 |
111 | (func (export "as-select-first") (param i32 i32) (result i32)
112 | (select (unreachable) (get_local 0) (get_local 1))
113 | )
114 | (func (export "as-select-second") (param i32 i32) (result i32)
115 | (select (get_local 0) (unreachable) (get_local 1))
116 | )
117 | (func (export "as-select-cond") (result i32)
118 | (select (i32.const 0) (i32.const 1) (unreachable))
119 | )
120 |
121 | (func (export "as-call-first")
122 | (call $dummy3 (unreachable) (i32.const 2) (i32.const 3))
123 | )
124 | (func (export "as-call-mid")
125 | (call $dummy3 (i32.const 1) (unreachable) (i32.const 3))
126 | )
127 | (func (export "as-call-last")
128 | (call $dummy3 (i32.const 1) (i32.const 2) (unreachable))
129 | )
130 |
131 | (type $sig (func (param i32 i32 i32)))
132 | (table anyfunc (elem $dummy3))
133 | (func (export "as-call_indirect-func")
134 | (call_indirect (type $sig)
135 | (unreachable) (i32.const 1) (i32.const 2) (i32.const 3)
136 | )
137 | )
138 | (func (export "as-call_indirect-first")
139 | (call_indirect (type $sig)
140 | (i32.const 0) (unreachable) (i32.const 2) (i32.const 3)
141 | )
142 | )
143 | (func (export "as-call_indirect-mid")
144 | (call_indirect (type $sig)
145 | (i32.const 0) (i32.const 1) (unreachable) (i32.const 3)
146 | )
147 | )
148 | (func (export "as-call_indirect-last")
149 | (call_indirect (type $sig)
150 | (i32.const 0) (i32.const 1) (i32.const 2) (unreachable)
151 | )
152 | )
153 |
154 | (func (export "as-set_local-value") (local f32)
155 | (set_local 0 (unreachable))
156 | )
157 |
158 | (memory 1)
159 | (func (export "as-load-address") (result f32)
160 | (f32.load (unreachable))
161 | )
162 | (func (export "as-loadN-address") (result i64)
163 | (i64.load8_s (unreachable))
164 | )
165 |
166 | (func (export "as-store-address")
167 | (f64.store (unreachable) (f64.const 7))
168 | )
169 | (func (export "as-store-value")
170 | (i64.store (i32.const 2) (unreachable))
171 | )
172 |
173 | (func (export "as-storeN-address")
174 | (i32.store8 (unreachable) (i32.const 7))
175 | )
176 | (func (export "as-storeN-value")
177 | (i64.store16 (i32.const 2) (unreachable))
178 | )
179 |
180 | (func (export "as-unary-operand") (result f32)
181 | (f32.neg (unreachable))
182 | )
183 |
184 | (func (export "as-binary-left") (result i32)
185 | (i32.add (unreachable) (i32.const 10))
186 | )
187 | (func (export "as-binary-right") (result i64)
188 | (i64.sub (i64.const 10) (unreachable))
189 | )
190 |
191 | (func (export "as-test-operand") (result i32)
192 | (i32.eqz (unreachable))
193 | )
194 |
195 | (func (export "as-compare-left") (result i32)
196 | (f64.le (unreachable) (f64.const 10))
197 | )
198 | (func (export "as-compare-right") (result i32)
199 | (f32.ne (f32.const 10) (unreachable))
200 | )
201 |
202 | (func (export "as-convert-operand") (result i32)
203 | (i32.wrap/i64 (unreachable))
204 | )
205 |
206 | (func (export "as-grow_memory-size") (result i32)
207 | (grow_memory (unreachable))
208 | )
209 | )
210 |
211 | (assert_trap (invoke "type-i32") "unreachable")
212 | (assert_trap (invoke "type-i64") "unreachable")
213 | (assert_trap (invoke "type-f32") "unreachable")
214 | (assert_trap (invoke "type-f64") "unreachable")
215 |
216 | (assert_trap (invoke "as-func-first") "unreachable")
217 | (assert_trap (invoke "as-func-mid") "unreachable")
218 | (assert_trap (invoke "as-func-last") "unreachable")
219 | (assert_trap (invoke "as-func-value") "unreachable")
220 |
221 | (assert_trap (invoke "as-block-first") "unreachable")
222 | (assert_trap (invoke "as-block-mid") "unreachable")
223 | (assert_trap (invoke "as-block-last") "unreachable")
224 | (assert_trap (invoke "as-block-value") "unreachable")
225 | (assert_return (invoke "as-block-broke") (i32.const 1))
226 |
227 | (assert_trap (invoke "as-loop-first") "unreachable")
228 | (assert_trap (invoke "as-loop-mid") "unreachable")
229 | (assert_trap (invoke "as-loop-last") "unreachable")
230 | (assert_return (invoke "as-loop-broke") (i32.const 1))
231 |
232 | (assert_trap (invoke "as-br-value") "unreachable")
233 |
234 | (assert_trap (invoke "as-br_if-cond") "unreachable")
235 | (assert_trap (invoke "as-br_if-value") "unreachable")
236 | (assert_trap (invoke "as-br_if-value-cond") "unreachable")
237 |
238 | (assert_trap (invoke "as-br_table-index") "unreachable")
239 | (assert_trap (invoke "as-br_table-value") "unreachable")
240 | (assert_trap (invoke "as-br_table-value-2") "unreachable")
241 | (assert_trap (invoke "as-br_table-value-index") "unreachable")
242 | (assert_trap (invoke "as-br_table-value-and-index") "unreachable")
243 |
244 | (assert_trap (invoke "as-return-value") "unreachable")
245 |
246 | (assert_trap (invoke "as-if-cond") "unreachable")
247 | (assert_trap (invoke "as-if-then" (i32.const 1) (i32.const 6)) "unreachable")
248 | (assert_return (invoke "as-if-then" (i32.const 0) (i32.const 6)) (i32.const 6))
249 | (assert_trap (invoke "as-if-else" (i32.const 0) (i32.const 6)) "unreachable")
250 | (assert_return (invoke "as-if-else" (i32.const 1) (i32.const 6)) (i32.const 6))
251 |
252 | (assert_trap (invoke "as-select-first" (i32.const 0) (i32.const 6)) "unreachable")
253 | (assert_trap (invoke "as-select-first" (i32.const 1) (i32.const 6)) "unreachable")
254 | (assert_trap (invoke "as-select-second" (i32.const 0) (i32.const 6)) "unreachable")
255 | (assert_trap (invoke "as-select-second" (i32.const 1) (i32.const 6)) "unreachable")
256 | (assert_trap (invoke "as-select-cond") "unreachable")
257 |
258 | (assert_trap (invoke "as-call-first") "unreachable")
259 | (assert_trap (invoke "as-call-mid") "unreachable")
260 | (assert_trap (invoke "as-call-last") "unreachable")
261 |
262 | (assert_trap (invoke "as-call_indirect-func") "unreachable")
263 | (assert_trap (invoke "as-call_indirect-first") "unreachable")
264 | (assert_trap (invoke "as-call_indirect-mid") "unreachable")
265 | (assert_trap (invoke "as-call_indirect-last") "unreachable")
266 |
267 | (assert_trap (invoke "as-set_local-value") "unreachable")
268 |
269 | (assert_trap (invoke "as-load-address") "unreachable")
270 | (assert_trap (invoke "as-loadN-address") "unreachable")
271 |
272 | (assert_trap (invoke "as-store-address") "unreachable")
273 | (assert_trap (invoke "as-store-value") "unreachable")
274 | (assert_trap (invoke "as-storeN-address") "unreachable")
275 | (assert_trap (invoke "as-storeN-value") "unreachable")
276 |
277 | (assert_trap (invoke "as-unary-operand") "unreachable")
278 |
279 | (assert_trap (invoke "as-binary-left") "unreachable")
280 | (assert_trap (invoke "as-binary-right") "unreachable")
281 |
282 | (assert_trap (invoke "as-test-operand") "unreachable")
283 |
284 | (assert_trap (invoke "as-compare-left") "unreachable")
285 | (assert_trap (invoke "as-compare-right") "unreachable")
286 |
287 | (assert_trap (invoke "as-convert-operand") "unreachable")
288 |
289 | (assert_trap (invoke "as-grow_memory-size") "unreachable")
290 |
291 |
--------------------------------------------------------------------------------
/tests/failing/unwind.wast:
--------------------------------------------------------------------------------
1 | ;; Test that control-flow transfer unwinds stack and it can be anything after.
2 |
3 | (module
4 | (func (export "func-unwind-by-unreachable")
5 | (i32.const 3) (i64.const 1) (unreachable)
6 | )
7 | (func (export "func-unwind-by-br")
8 | (i32.const 3) (i64.const 1) (br 0)
9 | )
10 | (func (export "func-unwind-by-br-value") (result i32)
11 | (i32.const 3) (i64.const 1) (br 0 (i32.const 9))
12 | )
13 | (func (export "func-unwind-by-br_table")
14 | (i32.const 3) (i64.const 1) (br_table 0 (i32.const 0))
15 | )
16 | (func (export "func-unwind-by-br_table-value") (result i32)
17 | (i32.const 3) (i64.const 1) (br_table 0 (i32.const 9) (i32.const 0))
18 | )
19 | (func (export "func-unwind-by-return") (result i32)
20 | (i32.const 3) (i64.const 1) (return (i32.const 9))
21 | )
22 |
23 | (func (export "block-unwind-by-unreachable")
24 | (block (i32.const 3) (i64.const 1) (unreachable))
25 | )
26 | (func (export "block-unwind-by-br") (result i32)
27 | (block (i32.const 3) (i64.const 1) (br 0)) (i32.const 9)
28 | )
29 | (func (export "block-unwind-by-br-value") (result i32)
30 | (block (result i32) (i32.const 3) (i64.const 1) (br 0 (i32.const 9)))
31 | )
32 | (func (export "block-unwind-by-br_table") (result i32)
33 | (block (i32.const 3) (i64.const 1) (br_table 0 (i32.const 0))) (i32.const 9)
34 | )
35 | (func (export "block-unwind-by-br_table-value") (result i32)
36 | (block (result i32)
37 | (i32.const 3) (i64.const 1) (br_table 0 (i32.const 9) (i32.const 0))
38 | )
39 | )
40 | (func (export "block-unwind-by-return") (result i32)
41 | (block (result i32) (i32.const 3) (i64.const 1) (return (i32.const 9)))
42 | )
43 |
44 | (func (export "block-nested-unwind-by-unreachable") (result i32)
45 | (block (result i32) (i32.const 3) (block (i64.const 1) (unreachable)))
46 | )
47 | (func (export "block-nested-unwind-by-br") (result i32)
48 | (block (i32.const 3) (block (i64.const 1) (br 1)) (drop)) (i32.const 9)
49 | )
50 | (func (export "block-nested-unwind-by-br-value") (result i32)
51 | (block (result i32)
52 | (i32.const 3) (block (i64.const 1) (br 1 (i32.const 9)))
53 | )
54 | )
55 | (func (export "block-nested-unwind-by-br_table") (result i32)
56 | (block
57 | (i32.const 3) (block (i64.const 1) (br_table 1 (i32.const 1)))
58 | (drop)
59 | )
60 | (i32.const 9)
61 | )
62 | (func (export "block-nested-unwind-by-br_table-value") (result i32)
63 | (block (result i32)
64 | (i32.const 3)
65 | (block (i64.const 1) (br_table 1 (i32.const 9) (i32.const 1)))
66 | )
67 | )
68 | (func (export "block-nested-unwind-by-return") (result i32)
69 | (block (result i32)
70 | (i32.const 3) (block (i64.const 1) (return (i32.const 9)))
71 | )
72 | )
73 |
74 | (func (export "unary-after-unreachable") (result i32)
75 | (f32.const 0) (unreachable) (i64.eqz)
76 | )
77 | (func (export "unary-after-br") (result i32)
78 | (block (result i32) (f32.const 0) (br 0 (i32.const 9)) (i64.eqz))
79 | )
80 | (func (export "unary-after-br_table") (result i32)
81 | (block (result i32)
82 | (f32.const 0) (br_table 0 0 (i32.const 9) (i32.const 0)) (i64.eqz)
83 | )
84 | )
85 | (func (export "unary-after-return") (result i32)
86 | (f32.const 0) (return (i32.const 9)) (i64.eqz)
87 | )
88 |
89 | (func (export "binary-after-unreachable") (result i32)
90 | (f32.const 0) (f64.const 1) (unreachable) (i64.eq)
91 | )
92 | (func (export "binary-after-br") (result i32)
93 | (block (result i32)
94 | (f32.const 0) (f64.const 1) (br 0 (i32.const 9)) (i64.eq)
95 | )
96 | )
97 | (func (export "binary-after-br_table") (result i32)
98 | (block (result i32)
99 | (f32.const 0) (f64.const 1) (br_table 0 (i32.const 9) (i32.const 0))
100 | (i64.eq)
101 | )
102 | )
103 | (func (export "binary-after-return") (result i32)
104 | (f32.const 0) (f64.const 1) (return (i32.const 9)) (i64.eq)
105 | )
106 |
107 | (func (export "select-after-unreachable") (result i32)
108 | (f32.const 0) (f64.const 1) (i64.const 0) (unreachable) (select)
109 | )
110 | (func (export "select-after-br") (result i32)
111 | (block (result i32)
112 | (f32.const 0) (f64.const 1) (i64.const 0) (br 0 (i32.const 9)) (select)
113 | )
114 | )
115 | (func (export "select-after-br_table") (result i32)
116 | (block (result i32)
117 | (f32.const 0) (f64.const 1) (i64.const 0)
118 | (br_table 0 (i32.const 9) (i32.const 0))
119 | (select)
120 | )
121 | )
122 | (func (export "select-after-return") (result i32)
123 | (f32.const 0) (f64.const 1) (i64.const 1) (return (i32.const 9)) (select)
124 | )
125 |
126 | (func (export "block-value-after-unreachable") (result i32)
127 | (block (result i32) (f32.const 0) (unreachable))
128 | )
129 | (func (export "block-value-after-br") (result i32)
130 | (block (result i32) (f32.const 0) (br 0 (i32.const 9)))
131 | )
132 | (func (export "block-value-after-br_table") (result i32)
133 | (block (result i32)
134 | (f32.const 0) (br_table 0 0 (i32.const 9) (i32.const 0))
135 | )
136 | )
137 | (func (export "block-value-after-return") (result i32)
138 | (block (result i32) (f32.const 0) (return (i32.const 9)))
139 | )
140 |
141 | (func (export "loop-value-after-unreachable") (result i32)
142 | (loop (result i32) (f32.const 0) (unreachable))
143 | )
144 | (func (export "loop-value-after-br") (result i32)
145 | (block (result i32) (loop (result i32) (f32.const 0) (br 1 (i32.const 9))))
146 | )
147 | (func (export "loop-value-after-br_table") (result i32)
148 | (block (result i32)
149 | (loop (result i32)
150 | (f32.const 0) (br_table 1 1 (i32.const 9) (i32.const 0))
151 | )
152 | )
153 | )
154 | (func (export "loop-value-after-return") (result i32)
155 | (loop (result i32) (f32.const 0) (return (i32.const 9)))
156 | )
157 | )
158 |
159 | (assert_trap (invoke "func-unwind-by-unreachable") "unreachable")
160 | (assert_return (invoke "func-unwind-by-br"))
161 | (assert_return (invoke "func-unwind-by-br-value") (i32.const 9))
162 | (assert_return (invoke "func-unwind-by-br_table"))
163 | (assert_return (invoke "func-unwind-by-br_table-value") (i32.const 9))
164 | (assert_return (invoke "func-unwind-by-return") (i32.const 9))
165 |
166 | (assert_trap (invoke "block-unwind-by-unreachable") "unreachable")
167 | (assert_return (invoke "block-unwind-by-br") (i32.const 9))
168 | (assert_return (invoke "block-unwind-by-br-value") (i32.const 9))
169 | (assert_return (invoke "block-unwind-by-br_table") (i32.const 9))
170 | (assert_return (invoke "block-unwind-by-br_table-value") (i32.const 9))
171 | (assert_return (invoke "block-unwind-by-return") (i32.const 9))
172 |
173 | (assert_trap (invoke "block-nested-unwind-by-unreachable") "unreachable")
174 | (assert_return (invoke "block-nested-unwind-by-br") (i32.const 9))
175 | (assert_return (invoke "block-nested-unwind-by-br-value") (i32.const 9))
176 | (assert_return (invoke "block-nested-unwind-by-br_table") (i32.const 9))
177 | (assert_return (invoke "block-nested-unwind-by-br_table-value") (i32.const 9))
178 | (assert_return (invoke "block-nested-unwind-by-return") (i32.const 9))
179 |
180 | (assert_trap (invoke "unary-after-unreachable") "unreachable")
181 | (assert_return (invoke "unary-after-br") (i32.const 9))
182 | (assert_return (invoke "unary-after-br_table") (i32.const 9))
183 | (assert_return (invoke "unary-after-return") (i32.const 9))
184 |
185 | (assert_trap (invoke "binary-after-unreachable") "unreachable")
186 | (assert_return (invoke "binary-after-br") (i32.const 9))
187 | (assert_return (invoke "binary-after-br_table") (i32.const 9))
188 | (assert_return (invoke "binary-after-return") (i32.const 9))
189 |
190 | (assert_trap (invoke "select-after-unreachable") "unreachable")
191 | (assert_return (invoke "select-after-br") (i32.const 9))
192 | (assert_return (invoke "select-after-br_table") (i32.const 9))
193 | (assert_return (invoke "select-after-return") (i32.const 9))
194 |
195 | (assert_trap (invoke "block-value-after-unreachable") "unreachable")
196 | (assert_return (invoke "block-value-after-br") (i32.const 9))
197 | (assert_return (invoke "block-value-after-br_table") (i32.const 9))
198 | (assert_return (invoke "block-value-after-return") (i32.const 9))
199 |
200 | (assert_trap (invoke "loop-value-after-unreachable") "unreachable")
201 | (assert_return (invoke "loop-value-after-br") (i32.const 9))
202 | (assert_return (invoke "loop-value-after-br_table") (i32.const 9))
203 | (assert_return (invoke "loop-value-after-return") (i32.const 9))
204 |
--------------------------------------------------------------------------------
/tests/spec/golden/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdiehl/wasm/f81d757210a3fd0a5df08a26379359591a8f695e/tests/spec/golden/.gitkeep
--------------------------------------------------------------------------------
/tests/spec/golden/fac.wasm:
--------------------------------------------------------------------------------
1 | Length: 47 (0x2f) bytes
2 | 0000: 00 61 73 6d 01 01 00 7f 02 01 09 00 00 15 00 00 .asm............
3 | 0010: 00 1a 00 04 51 20 00 00 00 00 42 00 42 01 7e 20 ....Q ....B.B.~
4 | 0020: 00 00 00 00 12 7d 20 00 00 00 00 42 01 06 00 .....} ....B...
5 |
--------------------------------------------------------------------------------
/tests/spec/golden/simple.wasm:
--------------------------------------------------------------------------------
1 | Length: 23 (0x17) bytes
2 | 0000: 00 61 73 6d 01 01 00 7f 02 01 09 00 00 15 00 00 .asm............
3 | 0010: 00 02 00 41 00 06 00 ...A...
4 |
--------------------------------------------------------------------------------
/tests/spec/input/add.wast:
--------------------------------------------------------------------------------
1 | (module
2 | (func $add (param $lhs i32) (param $rhs i32) (result i32)
3 | get_local $lhs
4 | get_local $rhs
5 | i32.add)
6 | (export "add" (func $add))
7 | )
8 |
--------------------------------------------------------------------------------
/tests/spec/input/empty.wast:
--------------------------------------------------------------------------------
1 | (module)
2 |
--------------------------------------------------------------------------------
/tests/spec/input/fac.wast:
--------------------------------------------------------------------------------
1 | (module
2 |
3 | (func $fac-rec (param $n i64) (result i64)
4 | (if_else (i64.eq (get_local $n) (i64.const 0))
5 | (i64.const 1)
6 | (i64.mul
7 | (get_local $n)
8 | (call $fac-rec (i64.sub (get_local $n) (i64.const 1)))
9 | )
10 | )
11 | )
12 |
13 | )
14 |
--------------------------------------------------------------------------------
/tests/spec/input/log.wast:
--------------------------------------------------------------------------------
1 | (module
2 | (import "console" "log" (func $log (param i32)))
3 | (func (export "logIt")
4 | i32.const 13
5 | call $log))
6 |
--------------------------------------------------------------------------------
/tests/spec/input/shared.wast:
--------------------------------------------------------------------------------
1 | (module
2 | (import "js" "memory" (memory 1))
3 | (import "js" "table" (table 1 anyfunc))
4 | (elem (i32.const 0) $shared0func)
5 | (func $shared0func (result i32)
6 | i32.const 0
7 | i32.load)
8 | )
9 |
--------------------------------------------------------------------------------
/tests/spec/input/simple.wast:
--------------------------------------------------------------------------------
1 | (module
2 | (func $foo (result i32) (i32.const 0))
3 | )
4 |
--------------------------------------------------------------------------------
/tests/spec/output/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdiehl/wasm/f81d757210a3fd0a5df08a26379359591a8f695e/tests/spec/output/.gitkeep
--------------------------------------------------------------------------------
/wasm.cabal:
--------------------------------------------------------------------------------
1 | -- This file has been generated from package.yaml by hpack version 0.20.0.
2 | --
3 | -- see: https://github.com/sol/hpack
4 | --
5 | -- hash: 9f4c705c2f82e92dc4d68087fe5387cf1e6e87ff3a0d416d673eda65891e0fbe
6 |
7 | name: wasm
8 | version: 0.1
9 | author: Stephen Diehl
10 | maintainer: stephen.m.diehl@gmail.com
11 | license: MIT
12 | license-file: LICENSE
13 | build-type: Simple
14 | cabal-version: >= 1.10
15 |
16 | extra-source-files:
17 | README.md
18 | src/Language/Wasm/Lexer.x
19 | src/Language/Wasm/Parser.y
20 |
21 | library
22 | hs-source-dirs:
23 | src
24 | ghc-options: -Wwarn -fwarn-incomplete-patterns -fwarn-unused-imports
25 | build-depends:
26 | ansi-wl-pprint >=0.6 && <0.7
27 | , array >=0.5 && <0.6
28 | , base >=4.6 && <5.0
29 | , binary >=0.7 && <0.9
30 | , bytestring >=0.10
31 | , cereal >=0.4 && <0.6
32 | , containers >=0.5 && <0.6
33 | , directory >=1.2
34 | , mtl >=2.2 && <3.0
35 | , optparse-applicative >=0.11 && <0.15
36 | , pretty >=1.1 && <1.2
37 | , pretty-hex >=0.1
38 | , pretty-show >=1.6 && <1.7
39 | , process >=1.1
40 | , text >=1.1
41 | , transformers >=0.4 && <0.6
42 | , wl-pprint-text >=1.0 && <2.0
43 | build-tools:
44 | alex >=3.1.3
45 | , happy >=1.9.4
46 | exposed-modules:
47 | Language.Wasm.Core
48 | Language.Wasm.Pretty
49 | Language.Wasm.Syntax
50 | Language.Wasm.Binary
51 | Language.Wasm.Lexer
52 | Language.Wasm.Parser
53 | Language.Wasm.Entry
54 | other-modules:
55 | Language.Wasm.Monad
56 | Language.Wasm.Position
57 | default-language: Haskell2010
58 |
59 | executable wasm
60 | main-is: Main.hs
61 | hs-source-dirs:
62 | exec
63 | build-depends:
64 | base >=4.6 && <5.0
65 | , wasm ==0.1
66 | build-tools:
67 | alex >=3.1.3
68 | , happy >=1.9.4
69 | other-modules:
70 | Paths_wasm
71 | default-language: Haskell2010
72 |
73 | test-suite test
74 | type: exitcode-stdio-1.0
75 | main-is: Test.hs
76 | hs-source-dirs:
77 | tests
78 | build-depends:
79 | base >=4.6 && <5.0
80 | , bytestring >=0.10 && <0.11
81 | , cereal >=0.4 && <0.6
82 | , filepath >=1.3 && <1.5
83 | , mtl ==2.2.1
84 | , pretty-hex >=0.1
85 | , tasty >=0.7
86 | , tasty-golden >=2.2 && <2.4
87 | , tasty-hunit >=0.4.1 && <0.10
88 | , text >=1.1 && <1.3
89 | , wasm ==0.1
90 | build-tools:
91 | alex >=3.1.3
92 | , happy >=1.9.4
93 | other-modules:
94 | Paths_wasm
95 | default-language: Haskell2010
96 |
--------------------------------------------------------------------------------
/watch:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ghcid --command="stack repl wasm:lib --no-docker --silent"
4 |
--------------------------------------------------------------------------------