├── .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 | [![Build Status](https://travis-ci.org/haskell-wasm/wasm.svg?branch=master)](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 | --------------------------------------------------------------------------------