├── .gitignore ├── COPYING ├── Cargo.toml ├── LICENSE-MIT ├── README.md ├── UNLICENSE ├── examples ├── print_info.rs ├── run_hello_module.rs ├── run_module.rs └── run_wast_test.rs ├── src ├── hexfloat.rs ├── interp.rs ├── lib.rs ├── module.rs ├── ops.rs ├── reader.rs ├── sexpr.rs ├── testcase.rs └── types.rs └── test ├── block.wast ├── br.wast ├── br_if.wast ├── br_table.wast ├── break-drop.wast ├── call.wast ├── call_indirect.wast ├── conversions.wast ├── endianness.wast ├── exports.wast ├── f32.wast ├── f32_cmp.wast ├── f64.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 ├── i32.wast ├── i64.wast ├── imports.wast ├── int_exprs.wast ├── int_literals.wast ├── labels.wast ├── left-to-right.wast ├── loop.wast ├── memory.wast ├── memory_redundancy.wast ├── memory_trap.wast ├── names.wast ├── nan-propagation.wast ├── nop.wast ├── resizing.wast ├── return.wast ├── select.wast ├── set_local.wast ├── start.wast ├── store_retval.wast ├── switch.wast ├── traps.wast ├── typecheck.wast └── unreachable.wast /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | This project is dual-licensed under the Unlicense and MIT licenses. 2 | 3 | You may use this code under the terms of either license. 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wasm" 3 | version = "0.1.0" 4 | authors = ["Joshua Warner "] 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Joshua Warner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | `wasm` is a library for reading and running [WebAssembly](http://webassembly.github.io) modules. 2 | 3 | Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org). 4 | -------------------------------------------------------------------------------- /UNLICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /examples/print_info.rs: -------------------------------------------------------------------------------- 1 | extern crate wasm; 2 | 3 | use std::{env, str}; 4 | use std::fs::File; 5 | use std::io::Read; 6 | 7 | fn to_hex_string(bytes: &[u8]) -> String { 8 | bytes.iter() 9 | .map(|b| format!("{:02X}", b)) 10 | .collect::>().join(" ") 11 | } 12 | 13 | fn main() { 14 | let args = env::args().collect::>(); 15 | if args.len() != 2 { 16 | println!("Usage: {} somefile.wasm", args[0]); 17 | return; 18 | } 19 | 20 | let mut contents = Vec::new(); 21 | File::open(&args[1]).expect("readable file").read_to_end(&mut contents).expect("read succeeds"); 22 | 23 | let m = wasm::Module::parse(&contents); 24 | 25 | println!("imports:"); 26 | for i in m.imports { 27 | println!(" {}.{}{}", 28 | str::from_utf8(i.module_name).unwrap(), 29 | str::from_utf8(i.function_name).unwrap(), 30 | m.types[i.function_type.0]); 31 | } 32 | 33 | println!("functions:"); 34 | for (i, f) in m.functions.iter().enumerate() { 35 | let name = m.names.get(i) 36 | .and_then(|e| str::from_utf8(e.function_name).ok()) 37 | .unwrap_or(""); 38 | println!(" {}{}", name, m.types[f.0]); 39 | 40 | let code = &m.code[i]; 41 | 42 | for l in &code.locals { 43 | println!(" local {}[{}]", l.0, l.1); 44 | } 45 | 46 | for l in code.block_ops() { 47 | println!("{}", wasm::ops::Indented(4, l)); 48 | } 49 | } 50 | 51 | println!("exports:"); 52 | for e in m.exports { 53 | let name = m.names.get(e.function_index.0) 54 | .and_then(|e| str::from_utf8(e.function_name).ok()) 55 | .unwrap_or(""); 56 | let ty = m.functions[e.function_index.0]; 57 | println!(" {} = {}{}", str::from_utf8(e.function_name).unwrap(), name, m.types[ty.0]); 58 | } 59 | 60 | println!("dynamic function table:"); 61 | for (i, t) in m.table.iter().enumerate() { 62 | let name = m.names.get(t.0) 63 | .and_then(|e| str::from_utf8(e.function_name).ok()) 64 | .unwrap_or(""); 65 | let ty = m.functions[t.0]; 66 | println!(" {} = {}{}", i, name, m.types[ty.0]); 67 | } 68 | 69 | println!("memory info:"); 70 | println!(" initial_64k_pages: {}", m.memory_info.initial_64k_pages); 71 | println!(" maximum_64k_pages: {}", m.memory_info.maximum_64k_pages); 72 | println!(" is_exported: {}", m.memory_info.is_exported); 73 | 74 | println!("start function:"); 75 | if let Some(i) = m.start_function_index { 76 | let name = m.names.get(i.0) 77 | .and_then(|e| str::from_utf8(e.function_name).ok()) 78 | .unwrap_or(""); 79 | let ty = m.functions[i.0]; 80 | println!(" {}{}", name, m.types[ty.0]); 81 | } else { 82 | println!(" (None)"); 83 | } 84 | 85 | println!("initial memory:"); 86 | for ch in &m.memory_chunks { 87 | println!(" from {} to {}:", ch.offset, ch.offset + ch.data.len()); 88 | for line in ch.data.chunks(32) { 89 | println!(" {}", to_hex_string(line)); 90 | } 91 | } 92 | if m.memory_chunks.len() == 0 { 93 | println!(" (None)"); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /examples/run_hello_module.rs: -------------------------------------------------------------------------------- 1 | extern crate wasm; 2 | 3 | use std::{env, str}; 4 | use std::fs::File; 5 | use std::io::Read; 6 | use std::collections::HashMap; 7 | 8 | use wasm::Dynamic; 9 | 10 | fn main() { 11 | let args = env::args().collect::>(); 12 | if args.len() != 2 { 13 | println!("Usage: {} somefile.wasm", args[0]); 14 | return; 15 | } 16 | 17 | let mut contents = Vec::new(); 18 | File::open(&args[1]).expect("readable file").read_to_end(&mut contents).expect("read succeeds"); 19 | 20 | let module = wasm::Module::parse(&contents); 21 | 22 | let mut import_table = HashMap::new(); 23 | import_table.insert(&b"env"[..], Box::new(HelloEnvModule) as Box); 24 | let mut inst = wasm::Instance::new(&module, import_table); 25 | 26 | let main = module.find(b"main").unwrap(); 27 | 28 | inst.invoke(main, &[]); 29 | } 30 | 31 | struct HelloEnvModule; 32 | 33 | impl wasm::BoundInstance for HelloEnvModule { 34 | fn invoke_export(&mut self, memory: &mut wasm::Memory, func: wasm::ExportIndex, args: &[Dynamic]) -> wasm::InterpResult { 35 | match func.0 { 36 | 0 => { 37 | println!("{} {} {:?}", args[0].to_u32(), args[1].to_u32(), memory.get_bytes(args[0].to_u32()..(args[1].to_u32() + args[0].to_u32()))); 38 | let bytes = memory.get_bytes(args[0].to_u32()..(args[1].to_u32() + args[0].to_u32())); 39 | println!("{}", str::from_utf8(bytes).unwrap()); 40 | } 41 | _ => panic!() 42 | } 43 | wasm::InterpResult::Value(None) 44 | } 45 | fn export_by_name_and_type(&self, name: &[u8], ty: wasm::FunctionType<&[u8]>) -> wasm::ExportIndex { 46 | println!("looking for env {}", str::from_utf8(name).unwrap_or("")); 47 | wasm::ExportIndex(match name { 48 | b"puts" => 0, 49 | _ => panic!() 50 | }) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /examples/run_module.rs: -------------------------------------------------------------------------------- 1 | extern crate wasm; 2 | 3 | use std::{env, str}; 4 | use std::fs::File; 5 | use std::io::Read; 6 | use std::collections::HashMap; 7 | 8 | use wasm::Dynamic; 9 | 10 | fn main() { 11 | let args = env::args().collect::>(); 12 | if args.len() != 2 { 13 | println!("Usage: {} somefile.wasm", args[0]); 14 | return; 15 | } 16 | 17 | let mut contents = Vec::new(); 18 | File::open(&args[1]).expect("readable file").read_to_end(&mut contents).expect("read succeeds"); 19 | 20 | let module = wasm::Module::parse(&contents); 21 | 22 | let mut import_table = HashMap::new(); 23 | import_table.insert(&b"env"[..], Box::new(EmscriptenEnvModule) as Box); 24 | import_table.insert(&b"asm2wasm"[..], Box::new(EmscriptenAsm2WasmModule) as Box); 25 | let mut inst = wasm::Instance::new(&module, import_table); 26 | 27 | let esp = module.find(b"establishStackSpace").unwrap(); 28 | let main = module.find(b"_main").unwrap(); 29 | 30 | inst.invoke(esp, &[Dynamic::from_u32(4*1024), Dynamic::from_u32(16*1024)]); 31 | 32 | let res = inst.invoke(main, &[Dynamic::from_u32(0), Dynamic::from_u32(0)]); 33 | 34 | // println!("{}", Pr(res)); 35 | } 36 | 37 | struct EmscriptenEnvModule; 38 | 39 | impl wasm::BoundInstance for EmscriptenEnvModule { 40 | fn invoke_export(&mut self, memory: &mut wasm::Memory, func: wasm::ExportIndex, args: &[Dynamic]) -> wasm::InterpResult { 41 | match func.0 { 42 | 0 => { 43 | panic!("called abort"); 44 | } 45 | 1 => { 46 | panic!("called abortStackOverflow"); 47 | } 48 | 2 => { 49 | panic!("called nullFunc_ii"); 50 | } 51 | 3 => { 52 | panic!("called nullFunc_iiii"); 53 | } 54 | 4 => { 55 | panic!("called nullFunc_vi"); 56 | } 57 | 5 => { 58 | panic!("called _pthread_cleanup_pop"); 59 | } 60 | 6 => { 61 | panic!("called _abort"); 62 | } 63 | 7 => { 64 | panic!("called ___lock"); 65 | } 66 | 8 => { 67 | panic!("called ___syscall6"); 68 | } 69 | 9 => { 70 | panic!("called _pthread_cleanup_push"); 71 | } 72 | 10 => { 73 | panic!("called _sbrk"); 74 | } 75 | 11 => { 76 | panic!("called ___syscall140"); 77 | } 78 | 12 => { 79 | panic!("called _emscripten_memcpy_big"); 80 | } 81 | 13 => { 82 | panic!("called ___syscall54"); 83 | } 84 | 14 => { 85 | panic!("called ___unlock"); 86 | } 87 | 15 => { 88 | panic!("called ___syscall146"); 89 | } 90 | _ => panic!() 91 | } 92 | } 93 | fn export_by_name_and_type(&self, name: &[u8], ty: wasm::FunctionType<&[u8]>) -> wasm::ExportIndex { 94 | println!("looking for env {}", str::from_utf8(name).unwrap_or("")); 95 | wasm::ExportIndex(match name { 96 | b"abort" => 0, 97 | b"abortStackOverflow" => 1, 98 | b"nullFunc_ii" => 2, 99 | b"nullFunc_iiii" => 3, 100 | b"nullFunc_vi" => 4, 101 | b"_pthread_cleanup_pop" => 5, 102 | b"_abort" => 6, 103 | b"___lock" => 7, 104 | b"___syscall6" => 8, 105 | b"_pthread_cleanup_push" => 9, 106 | b"_sbrk" => 10, 107 | b"___syscall140" => 11, 108 | b"_emscripten_memcpy_big" => 12, 109 | b"___syscall54" => 13, 110 | b"___unlock" => 14, 111 | b"___syscall146" => 15, 112 | _ => panic!() 113 | }) 114 | } 115 | } 116 | 117 | struct EmscriptenAsm2WasmModule; 118 | 119 | impl wasm::BoundInstance for EmscriptenAsm2WasmModule { 120 | fn invoke_export(&mut self, memory: &mut wasm::Memory, func: wasm::ExportIndex, args: &[Dynamic]) -> wasm::InterpResult { 121 | for a in args { 122 | match a { 123 | &Dynamic::Int32(v) => println!("print: {}", v), 124 | &Dynamic::Int64(v) => println!("print: {}", v), 125 | &Dynamic::Float32(v) => println!("print: {}", v), 126 | &Dynamic::Float64(v) => println!("print: {}", v), 127 | } 128 | } 129 | panic!(); 130 | } 131 | fn export_by_name_and_type(&self, name: &[u8], ty: wasm::FunctionType<&[u8]>) -> wasm::ExportIndex { 132 | println!("looking for asm2wasm {}", str::from_utf8(name).unwrap_or("")); 133 | wasm::ExportIndex(0) 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /examples/run_wast_test.rs: -------------------------------------------------------------------------------- 1 | extern crate wasm; 2 | 3 | use std::env; 4 | use std::fs::File; 5 | use std::io::Read; 6 | 7 | 8 | fn main() { 9 | let args = env::args().collect::>(); 10 | if args.len() != 2 { 11 | println!("Usage: {} somefile.wast", args[0]); 12 | return; 13 | } 14 | 15 | let mut contents = Vec::new(); 16 | File::open(&args[1]).expect("readable file").read_to_end(&mut contents).expect("read succeeds"); 17 | 18 | let test = wasm::TestCase::parse(&contents); 19 | 20 | test.run_all(); 21 | } 22 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | 2 | mod reader; 3 | 4 | mod types; 5 | mod module; 6 | pub mod ops; 7 | mod interp; 8 | mod testcase; 9 | mod sexpr; 10 | mod hexfloat; 11 | 12 | pub use types::Dynamic; 13 | pub use module::{Module, FunctionIndex, ExportIndex, FunctionType}; 14 | pub use interp::{Instance, BoundInstance, InterpResult, Memory}; 15 | pub use testcase::TestCase; 16 | 17 | #[cfg(test)] 18 | mod test { 19 | use std::fs::{self, File}; 20 | use std::path::Path; 21 | use std::io::Read; 22 | 23 | // failing due to stack size limits 24 | // #[test] 25 | fn run_all_wast_tests() { 26 | for entry in fs::read_dir(Path::new("test")).unwrap() { 27 | let entry = entry.unwrap(); 28 | println!("running {:?}", entry.path()); 29 | 30 | let mut contents = Vec::new(); 31 | File::open(&entry.path()).expect("readable file").read_to_end(&mut contents).expect("read succeeds"); 32 | 33 | let test = ::testcase::TestCase::parse(&contents); 34 | 35 | test.run_all(); 36 | 37 | println!("\n\n\n\n"); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/reader.rs: -------------------------------------------------------------------------------- 1 | use std::str; 2 | 3 | pub struct Reader<'a> { 4 | buf: &'a [u8], 5 | pos: usize 6 | } 7 | 8 | #[derive(Debug)] 9 | pub enum ReadError { 10 | BadVarInt1(u32) 11 | } 12 | 13 | impl<'a> Reader<'a> { 14 | pub fn new(buf: &'a [u8]) -> Reader<'a> { 15 | Reader { 16 | buf: buf, 17 | pos: 0 18 | } 19 | } 20 | 21 | pub fn skip(&mut self, count: usize) { 22 | self.pos += count; 23 | if self.pos > self.buf.len() { 24 | panic!(); 25 | } 26 | } 27 | 28 | pub fn peek_u8(&self) -> u8 { 29 | self.buf[self.pos] 30 | } 31 | 32 | pub fn read_u8(&mut self) -> u8 { 33 | let res = self.buf[self.pos]; 34 | self.pos += 1; 35 | res 36 | } 37 | 38 | pub fn read_u32(&mut self) -> u32 { 39 | ((self.read_u8() as u32) << 0*8) + 40 | ((self.read_u8() as u32) << 1*8) + 41 | ((self.read_u8() as u32) << 2*8) + 42 | ((self.read_u8() as u32) << 3*8) 43 | } 44 | 45 | pub fn read_u64(&mut self) -> u64 { 46 | ((self.read_u8() as u64) << 0*8) + 47 | ((self.read_u8() as u64) << 1*8) + 48 | ((self.read_u8() as u64) << 2*8) + 49 | ((self.read_u8() as u64) << 3*8) + 50 | ((self.read_u8() as u64) << (4+0)*8) + 51 | ((self.read_u8() as u64) << (4+1)*8) + 52 | ((self.read_u8() as u64) << (4+2)*8) + 53 | ((self.read_u8() as u64) << (4+3)*8) 54 | } 55 | 56 | pub fn read_var_u32(&mut self) -> u32 { 57 | let mut res = 0; 58 | let mut shift = 0; 59 | loop { 60 | let b = self.read_u8() as u32; 61 | res |= (b & 0x7f) << shift; 62 | shift += 7; 63 | if (b >> 7) == 0 { 64 | break; 65 | } 66 | } 67 | res 68 | } 69 | 70 | pub fn read_var_u1(&mut self) -> Result { 71 | let r = self.read_var_u32(); 72 | match r { 73 | 0 => Ok(false), 74 | 1 => Ok(true), 75 | _ => Err(ReadError::BadVarInt1(r)), 76 | } 77 | } 78 | 79 | pub fn read_var_u64(&mut self) -> u64 { 80 | let mut res = 0; 81 | let mut shift = 0; 82 | loop { 83 | let b = self.read_u8() as u64; 84 | res |= (b & 0x7f) << shift; 85 | shift += 7; 86 | if (b >> 7) == 0 { 87 | break; 88 | } 89 | } 90 | res 91 | } 92 | 93 | pub fn read_var_i32(&mut self) -> i32 { 94 | let mut res = 0i32; 95 | let mut shift = 0; 96 | loop { 97 | let b = self.read_u8() as i32; 98 | res |= (b & 0x7f) << shift; 99 | shift += 7; 100 | if (b & 0x80) == 0 { 101 | if shift < 31 && (b & 0x40) != 0 { 102 | res |= -(1 << shift); 103 | } 104 | break; 105 | } 106 | } 107 | res 108 | } 109 | 110 | pub fn read_var_i64(&mut self) -> i64 { 111 | let mut res = 0i64; 112 | let mut shift = 0; 113 | loop { 114 | let b = self.read_u8() as i64; 115 | res |= (b & 0x7f) << shift; 116 | shift += 7; 117 | if (b & 0x80) == 0 { 118 | if shift < 31 && (b & 0x40) != 0 { 119 | res |= -(1 << shift); 120 | } 121 | break; 122 | } 123 | } 124 | res 125 | } 126 | 127 | pub fn read_bytes_with_len(&mut self, data_len: usize) -> &'a [u8] { 128 | let data = &self.buf[self.pos..self.pos + data_len]; 129 | self.pos += data_len; 130 | 131 | data 132 | } 133 | 134 | pub fn read_bytes(&mut self) -> &'a [u8] { 135 | let data_len = self.read_var_u32() as usize; 136 | self.read_bytes_with_len(data_len) 137 | } 138 | 139 | pub fn read_str(&mut self) -> &'a str { 140 | str::from_utf8(self.read_bytes()).unwrap() 141 | } 142 | 143 | pub fn into_remaining(self) -> &'a [u8] { 144 | &self.buf[self.pos..] 145 | } 146 | 147 | pub fn at_eof(&self) -> bool { 148 | self.pos >= self.buf.len() 149 | } 150 | 151 | pub fn position(&self) -> usize { 152 | self.pos 153 | } 154 | 155 | pub fn len(&self) -> usize { 156 | self.buf.len() 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/sexpr.rs: -------------------------------------------------------------------------------- 1 | use std::{fmt, str}; 2 | 3 | #[derive(Debug)] 4 | pub enum Sexpr { 5 | String(Vec), 6 | Identifier(Vec), 7 | Variable(Vec), 8 | List(Vec) 9 | } 10 | 11 | struct Parser<'a> { 12 | text: &'a [u8], 13 | pos: usize 14 | } 15 | 16 | fn is_ws_char(ch: u8) -> bool { 17 | ch == b' ' || ch == b'\n' || ch == b'\t' 18 | } 19 | 20 | fn is_sep_char(ch: u8) -> bool { 21 | ch == b'(' || ch == b')' || is_ws_char(ch) 22 | } 23 | 24 | fn parse_hex_digit(ch: u8) -> u8 { 25 | match ch { 26 | b'0'...b'9' => ch - b'0', 27 | b'a'...b'f' => ch - b'a' + 10, 28 | b'A'...b'F' => ch - b'A' + 10, 29 | _ => panic!(), 30 | } 31 | } 32 | 33 | fn unescape(text: &[u8]) -> Vec { 34 | let mut res = Vec::new(); 35 | 36 | enum State { 37 | Start, 38 | Esc, 39 | One(u8), 40 | } 41 | 42 | let mut state = State::Start; 43 | 44 | for ch in text { 45 | match state { 46 | State::Start => match *ch { 47 | b'\\' => state = State::Esc, 48 | _ => res.push(*ch), 49 | }, 50 | State::Esc => match *ch { 51 | b'0'...b'9' | b'a'...b'f' | b'A'...b'F' => 52 | state = State::One(parse_hex_digit(*ch)), 53 | b'n' => { 54 | res.push(b'\n'); 55 | state = State::Start; 56 | } 57 | b'\\' => { 58 | res.push(b'\\'); 59 | state = State::Start; 60 | } 61 | b'\"' => { 62 | res.push(b'\"'); 63 | state = State::Start; 64 | } 65 | _ => panic!("unexpected escape {}", *ch), 66 | }, 67 | State::One(val) => match *ch { 68 | b'0'...b'9' | b'a'...b'f' | b'A'...b'F' => { 69 | let d = parse_hex_digit(*ch); 70 | res.push(d + (val << 4)); 71 | state = State::Start; 72 | } 73 | _ => panic!("unexpected second escape {}", *ch), 74 | }, 75 | } 76 | } 77 | 78 | res 79 | } 80 | 81 | impl<'a> Parser<'a> { 82 | fn new(text: &'a str) -> Parser { 83 | Parser { 84 | text: text.as_bytes(), 85 | pos: 0 86 | } 87 | } 88 | 89 | fn skip_ws(&mut self) { 90 | loop { 91 | while self.pos < self.text.len() && is_ws_char(self.text[self.pos]) { 92 | self.pos += 1; 93 | } 94 | 95 | if self.pos + 1 < self.text.len() && 96 | self.text[self.pos] == ';' as u8 && 97 | self.text[self.pos + 1] == ';' as u8 { 98 | while self.pos < self.text.len() && self.text[self.pos] != b'\n' { 99 | self.pos += 1; 100 | } 101 | } else { 102 | break; 103 | } 104 | } 105 | } 106 | 107 | fn parse_item(&mut self) -> Sexpr { 108 | self.skip_ws(); 109 | 110 | if self.pos >= self.text.len() { 111 | panic!(); 112 | } 113 | 114 | let res = match self.text[self.pos] { 115 | b'(' => { 116 | let mut res = Vec::new(); 117 | 118 | self.pos += 1; 119 | 120 | self.skip_ws(); 121 | 122 | while self.text[self.pos] != b')' { 123 | res.push(self.parse_item()); 124 | } 125 | 126 | self.pos += 1; 127 | 128 | Sexpr::List(res) 129 | } 130 | b'"' => { 131 | let mut len = 1; 132 | 133 | loop { 134 | if self.pos + len >= self.text.len() { 135 | panic!(); 136 | } 137 | 138 | if self.text[self.pos + len] == b'\\' { 139 | len += 1; 140 | if len == self.text.len() { 141 | panic!(); 142 | } else { 143 | len += 1; 144 | } 145 | } 146 | 147 | if self.text[self.pos + len] == b'"' { 148 | len += 1; 149 | break; 150 | } 151 | len += 1; 152 | } 153 | let offset = self.pos + 1; 154 | self.pos += len; 155 | 156 | Sexpr::String(unescape(&self.text[offset..self.pos - 1])) 157 | } 158 | // x @ b'0'...b'9' => { 159 | // let mut len = 1; 160 | // loop { 161 | // if self.pos + len >= self.text.len() || is_sep_char(self.text[self.pos + len]) { 162 | // break; 163 | // } else { 164 | // match self.text[self.pos + len] { 165 | // b'0'...b'9' => {}, 166 | // _ => break; 167 | // } 168 | // panic!(); 169 | // } 170 | // len += 1; 171 | // } 172 | // let offset = self.pos; 173 | // self.pos += len; 174 | 175 | // Sexpr::Number(::std::str::from_utf8(&self.text[offset..self.pos]).unwrap().to_owned()) 176 | // } 177 | b'$' => { 178 | let mut len = 1; 179 | loop { 180 | if self.pos + len >= self.text.len() || is_sep_char(self.text[self.pos + len]) { 181 | break; 182 | } else if self.text[self.pos + len] == b'"' { 183 | panic!(); 184 | } 185 | len += 1; 186 | } 187 | let offset = self.pos + 1; 188 | self.pos += len; 189 | 190 | Sexpr::Variable(Vec::from(&self.text[offset..self.pos])) 191 | } 192 | x if !is_sep_char(x) => { 193 | let mut len = 1; 194 | loop { 195 | if self.pos + len >= self.text.len() || is_sep_char(self.text[self.pos + len]) { 196 | break; 197 | } 198 | len += 1; 199 | } 200 | let offset = self.pos; 201 | self.pos += len; 202 | 203 | Sexpr::Identifier(Vec::from(&self.text[offset..self.pos])) 204 | } 205 | _ => panic!() 206 | }; 207 | 208 | self.skip_ws(); 209 | 210 | res 211 | } 212 | 213 | fn at_end(&self) -> bool { 214 | self.pos >= self.text.len() 215 | } 216 | } 217 | 218 | impl Sexpr { 219 | pub fn parse(text: &str) -> Vec { 220 | let mut res = Vec::new(); 221 | let mut p = Parser::new(text); 222 | while !p.at_end() { 223 | res.push(p.parse_item()); 224 | } 225 | res 226 | } 227 | } 228 | 229 | 230 | impl fmt::Display for Sexpr { 231 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { 232 | match self { 233 | &Sexpr::String(ref text) | 234 | &Sexpr::Identifier(ref text) | 235 | &Sexpr::Variable(ref text) => write!(f, "{}", str::from_utf8(text).unwrap_or("")), 236 | &Sexpr::List(ref items) => { 237 | try!(write!(f, "(")); 238 | for (i, s) in items.iter().enumerate() { 239 | if i != 0 { 240 | try!(write!(f, " ")); 241 | } 242 | try!(write!(f, "{}", s)); 243 | } 244 | write!(f, ")") 245 | } 246 | } 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /src/types.rs: -------------------------------------------------------------------------------- 1 | use std::{str, mem, fmt}; 2 | use std::num::Wrapping; 3 | 4 | #[repr(u8)] 5 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] 6 | pub enum Type { 7 | Int32 = 1, 8 | Int64 = 2, 9 | Float32 = 3, 10 | Float64 = 4 11 | } 12 | 13 | impl Type { 14 | pub fn from_u8(val: u8) -> Type { 15 | if val < 1 || val > 4 { 16 | panic!(); 17 | } 18 | unsafe { mem::transmute(val) } 19 | } 20 | 21 | pub fn to_u8(&self) -> u8 { 22 | unsafe { mem::transmute(*self) } 23 | } 24 | 25 | pub fn size(&self) -> Size { 26 | match self { 27 | &Type::Int32 => Size::I32, 28 | &Type::Int64 => Size::I64, 29 | &Type::Float32 => Size::I32, 30 | &Type::Float64 => Size::I64, 31 | } 32 | } 33 | 34 | pub fn zero(&self) -> Dynamic { 35 | match self { 36 | &Type::Int32 => Dynamic::Int32(Wrapping(0)), 37 | &Type::Int64 => Dynamic::Int64(Wrapping(0)), 38 | &Type::Float32 => Dynamic::Float32(0f32), 39 | &Type::Float64 => Dynamic::Float64(0f64), 40 | } 41 | } 42 | } 43 | 44 | impl fmt::Display for Type { 45 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { 46 | match self { 47 | &Type::Int32 => write!(f, "i32"), 48 | &Type::Int64 => write!(f, "i64"), 49 | &Type::Float32 => write!(f, "f32"), 50 | &Type::Float64 => write!(f, "f64"), 51 | } 52 | } 53 | } 54 | 55 | #[derive(Copy, Clone)] 56 | pub enum Sign { 57 | Signed, 58 | Unsigned 59 | } 60 | 61 | impl Sign { 62 | pub fn text(self) -> &'static str { 63 | match self { 64 | Sign::Signed => "s", 65 | Sign::Unsigned => "u", 66 | } 67 | } 68 | } 69 | 70 | #[derive(Copy, Clone, Eq, PartialEq)] 71 | pub enum Size { 72 | I8, 73 | I16, 74 | I32, 75 | I64 76 | } 77 | 78 | impl Size { 79 | pub fn to_int(self) -> usize { 80 | match self { 81 | Size::I8 => 8, 82 | Size::I16 => 16, 83 | Size::I32 => 32, 84 | Size::I64 => 64, 85 | } 86 | } 87 | } 88 | 89 | #[derive(Copy, Clone)] 90 | pub enum IntType { 91 | Int32, 92 | Int64 93 | } 94 | 95 | impl IntType { 96 | pub fn to_type(self) -> Type { 97 | match self { 98 | IntType::Int32 => Type::Int32, 99 | IntType::Int64 => Type::Int64, 100 | } 101 | } 102 | // pub fn min_unsigned_value(self) -> u64 { 103 | // match self { 104 | // IntType::Int32 => 0u64, 105 | // IntType::Int64 => 0u64, 106 | // } 107 | // } 108 | pub fn max_unsigned_value(self) -> u64 { 109 | match self { 110 | IntType::Int32 => 4294967295u64, 111 | IntType::Int64 => 18446744073709551615u64, 112 | } 113 | } 114 | pub fn min_signed_value(self) -> i64 { 115 | match self { 116 | IntType::Int32 => -2147483648i64, 117 | IntType::Int64 => -9223372036854775808i64, 118 | } 119 | } 120 | pub fn max_signed_value(self) -> i64 { 121 | match self { 122 | IntType::Int32 => 2147483647i64, 123 | IntType::Int64 => 9223372036854775807i64, 124 | } 125 | } 126 | } 127 | 128 | impl fmt::Display for IntType { 129 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { 130 | write!(f, "{}", self.to_type()) 131 | } 132 | } 133 | 134 | #[derive(Copy, Clone)] 135 | pub enum FloatType { 136 | Float32, 137 | Float64 138 | } 139 | 140 | impl FloatType { 141 | pub fn to_type(self) -> Type { 142 | match self { 143 | FloatType::Float32 => Type::Float32, 144 | FloatType::Float64 => Type::Float64, 145 | } 146 | } 147 | } 148 | 149 | impl fmt::Display for FloatType { 150 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { 151 | write!(f, "{}", self.to_type()) 152 | } 153 | } 154 | 155 | #[derive(Clone, Copy, PartialEq)] 156 | pub enum Dynamic { 157 | Int32(Wrapping), 158 | Int64(Wrapping), 159 | Float32(f32), 160 | Float64(f64) 161 | } 162 | 163 | impl fmt::Display for Dynamic { 164 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { 165 | match self { 166 | &Dynamic::Int32(val) => write!(f, "i32:{}", val), 167 | &Dynamic::Int64(val) => write!(f, "i64:{}", val), 168 | &Dynamic::Float32(val) => write!(f, "f32:{}", val), 169 | &Dynamic::Float64(val) => write!(f, "f64:{}", val), 170 | } 171 | } 172 | } 173 | 174 | impl fmt::Debug for Dynamic { 175 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { 176 | fmt::Display::fmt(self, f) 177 | } 178 | } 179 | 180 | pub struct Pr(pub T); 181 | 182 | impl fmt::Display for Pr> { 183 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { 184 | match self { 185 | &Pr(Some(Dynamic::Int32(val))) => write!(f, "i32:{}", val), 186 | &Pr(Some(Dynamic::Int64(val))) => write!(f, "i64:{}", val), 187 | &Pr(Some(Dynamic::Float32(val))) => write!(f, "f32:{}", val), 188 | &Pr(Some(Dynamic::Float64(val))) => write!(f, "f64:{}", val), 189 | &Pr(None) => write!(f, "void") 190 | } 191 | } 192 | } 193 | 194 | impl fmt::Display for Pr> { 195 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { 196 | match self { 197 | &Pr(Some(Type::Int32)) => write!(f, "i32"), 198 | &Pr(Some(Type::Int64)) => write!(f, "i64"), 199 | &Pr(Some(Type::Float32)) => write!(f, "f32"), 200 | &Pr(Some(Type::Float64)) => write!(f, "f64"), 201 | &Pr(None) => write!(f, "void") 202 | } 203 | } 204 | } 205 | 206 | pub struct NoType(pub Dynamic); 207 | 208 | impl fmt::Display for NoType { 209 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { 210 | match self.0 { 211 | Dynamic::Int32(val) => write!(f, "{}", val), 212 | Dynamic::Int64(val) => write!(f, "{}", val), 213 | Dynamic::Float32(val) => write!(f, "{}", val), 214 | Dynamic::Float64(val) => write!(f, "{}", val), 215 | } 216 | } 217 | } 218 | 219 | impl Dynamic { 220 | pub fn to_wu32(self) -> Wrapping { 221 | match self { 222 | Dynamic::Int32(v) => v, 223 | _ => panic!() 224 | } 225 | } 226 | pub fn to_wu64(self) -> Wrapping { 227 | match self { 228 | Dynamic::Int64(v) => v, 229 | _ => panic!() 230 | } 231 | } 232 | pub fn to_wi32(self) -> Wrapping { 233 | match self { 234 | Dynamic::Int32(v) => Wrapping(v.0 as i32), 235 | _ => panic!() 236 | } 237 | } 238 | pub fn to_wi64(self) -> Wrapping { 239 | match self { 240 | Dynamic::Int64(v) => Wrapping(v.0 as i64), 241 | _ => panic!() 242 | } 243 | } 244 | pub fn to_u32(self) -> u32 { 245 | self.to_wu32().0 246 | } 247 | pub fn to_u64(self) -> u64 { 248 | self.to_wu64().0 249 | } 250 | pub fn to_i32(self) -> i32 { 251 | self.to_wi32().0 252 | } 253 | pub fn to_i64(self) -> i64 { 254 | self.to_wi64().0 255 | } 256 | pub fn to_int(self) -> Wrapping { 257 | match self { 258 | Dynamic::Int32(v) => Wrapping(v.0 as u64), 259 | Dynamic::Int64(v) => v, 260 | _ => panic!() 261 | } 262 | } 263 | pub fn to_float(self) -> f64 { 264 | match self { 265 | Dynamic::Float32(v) => v as f64, 266 | Dynamic::Float64(v) => v, 267 | _ => panic!() 268 | } 269 | } 270 | pub fn to_f32(self) -> f32 { 271 | match self { 272 | Dynamic::Float32(v) => v, 273 | _ => panic!() 274 | } 275 | } 276 | pub fn to_f64(self) -> f64 { 277 | match self { 278 | Dynamic::Float64(v) => v, 279 | _ => panic!() 280 | } 281 | } 282 | pub fn from_i32(val: i32) -> Dynamic { 283 | Dynamic::Int32(Wrapping(val as u32)) 284 | } 285 | pub fn from_i64(val: i64) -> Dynamic { 286 | Dynamic::Int64(Wrapping(val as u64)) 287 | } 288 | pub fn from_u32(val: u32) -> Dynamic { 289 | Dynamic::Int32(Wrapping(val)) 290 | } 291 | pub fn from_u64(val: u64) -> Dynamic { 292 | Dynamic::Int64(Wrapping(val)) 293 | } 294 | pub fn from_float(ty: FloatType, val: f64) -> Dynamic { 295 | match ty { 296 | FloatType::Float32 => Dynamic::Float32(val as f32), 297 | FloatType::Float64 => Dynamic::Float64(val), 298 | } 299 | } 300 | pub fn from_int(ty: IntType, val: u64) -> Dynamic { 301 | match ty { 302 | IntType::Int32 => Dynamic::Int32(Wrapping(val as u32)), 303 | IntType::Int64 => Dynamic::Int64(Wrapping(val)), 304 | } 305 | } 306 | 307 | pub fn get_type(&self) -> Type { 308 | match self { 309 | &Dynamic::Int32(_) => Type::Int32, 310 | &Dynamic::Int64(_) => Type::Int64, 311 | &Dynamic::Float32(_) => Type::Float32, 312 | &Dynamic::Float64(_) => Type::Float64, 313 | } 314 | } 315 | } 316 | -------------------------------------------------------------------------------- /test/block.wast: -------------------------------------------------------------------------------- 1 | ;; Test `block` opcode 2 | 3 | (module 4 | (func "empty" 5 | (block) 6 | (block $l) 7 | ) 8 | 9 | (func "singular" (result i32) 10 | (block (nop)) 11 | (block (i32.const 7)) 12 | ) 13 | 14 | (func $nop) 15 | (func "multi" (result i32) 16 | (block (call $nop) (call $nop) (call $nop) (call $nop)) 17 | (block (call $nop) (call $nop) (call $nop) (i32.const 8)) 18 | ) 19 | 20 | (func "nested" (result i32) 21 | (block (block (call $nop) (block) (nop)) (block (call $nop) (i32.const 9))) 22 | ) 23 | 24 | (func "deep" (result i32) 25 | (block (block (block (block (block (block (block (block (block (block 26 | (block (block (block (block (block (block (block (block (block (block 27 | (block (block (block (block (block (block (block (block (block (block 28 | (block (block (block (block (block (block (block (block (block (block 29 | (block (block (block (block (block (call $nop) (i32.const 150)))))) 30 | )))))))))) 31 | )))))))))) 32 | )))))))))) 33 | )))))))))) 34 | ) 35 | 36 | (func "as-unary-operand" (result i32) 37 | (i32.ctz (block (call $nop) (i32.const 13))) 38 | ) 39 | (func "as-binary-operand" (result i32) 40 | (i32.mul (block (call $nop) (i32.const 3)) (block (call $nop) (i32.const 4))) 41 | ) 42 | (func "as-test-operand" (result i32) 43 | (i32.eqz (block (call $nop) (i32.const 13))) 44 | ) 45 | (func "as-compare-operand" (result i32) 46 | (f32.gt (block (call $nop) (f32.const 3)) (block (call $nop) (f32.const 3))) 47 | ) 48 | 49 | (func "break-bare" (result i32) 50 | (block (br 0) (unreachable)) 51 | (block (br_if 0 (i32.const 1)) (unreachable)) 52 | (block (br_table 0 (i32.const 0)) (unreachable)) 53 | (block (br_table 0 0 0 (i32.const 1)) (unreachable)) 54 | (i32.const 19) 55 | ) 56 | (func "break-value" (result i32) 57 | (block (br 0 (i32.const 18)) (i32.const 19)) 58 | ) 59 | (func "break-repeated" (result i32) 60 | (block 61 | (br 0 (i32.const 18)) 62 | (br 0 (i32.const 19)) 63 | (br_if 0 (i32.const 20) (i32.const 0)) 64 | (br_if 0 (i32.const 20) (i32.const 1)) 65 | (br 0 (i32.const 21)) 66 | (br_table 0 (i32.const 22) (i32.const 4)) 67 | (br_table 0 0 0 (i32.const 23) (i32.const 1)) 68 | (i32.const 21) 69 | ) 70 | ) 71 | (func "break-inner" (result i32) 72 | (local i32) 73 | (set_local 0 (i32.const 0)) 74 | (set_local 0 (i32.add (get_local 0) (block (block (br 1 (i32.const 0x1)))))) 75 | (set_local 0 (i32.add (get_local 0) (block (block (br 0)) (i32.const 0x2)))) 76 | (set_local 0 (i32.add (get_local 0) (block (i32.ctz (br 0 (i32.const 0x4)))))) 77 | (set_local 0 (i32.add (get_local 0) (block (i32.ctz (block (br 1 (i32.const 0x8))))))) 78 | (get_local 0) 79 | ) 80 | 81 | (func "drop-mid" (result i32) 82 | (block (call $fx) (i32.const 7) (call $nop) (i32.const 8)) 83 | ) 84 | (func "drop-last" 85 | (block (call $nop) (call $fx) (nop) (i32.const 8)) 86 | ) 87 | (func "drop-break-void" 88 | (block (br 0 (nop))) 89 | (block (br 0 (call $nop))) 90 | (block (br_if 0 (nop) (i32.const 0))) 91 | (block (br_if 0 (nop) (i32.const 1))) 92 | (block (br_if 0 (call $nop) (i32.const 0))) 93 | (block (br_if 0 (call $nop) (i32.const 1))) 94 | (block (br_table 0 (nop) (i32.const 3))) 95 | (block (br_table 0 0 0 (nop) (i32.const 2))) 96 | ) 97 | (func "drop-break-value" 98 | (block (br 0 (i32.const 12))) 99 | (block (br_if 0 (i32.const 11) (i32.const 0))) 100 | (block (br_if 0 (i32.const 10) (i32.const 1))) 101 | (block (br_table 0 (i32.const 9) (i32.const 5))) 102 | (block (br_table 0 0 0 (i32.const 8) (i32.const 1))) 103 | ) 104 | (func "drop-break-value-heterogeneous" 105 | (block (br 0 (i32.const 8)) (br 0 (f64.const 8)) (br 0 (f32.const 8))) 106 | (block (br 0 (i32.const 8)) (br 0) (br 0 (f64.const 8))) 107 | (block (br 0 (i32.const 8)) (br 0 (call $nop)) (br 0 (f64.const 8))) 108 | (block (br 0 (i32.const 8)) (br 0) (br 0 (f32.const 8)) (i64.const 3)) 109 | (block (br 0) (br 0 (i32.const 8)) (br 0 (f64.const 8)) (br 0 (nop))) 110 | (block (br 0) (br 0 (i32.const 8)) (br 0 (f32.const 8)) (i64.const 3)) 111 | (block (block (br 0) (br 1 (i32.const 8))) (br 0 (f32.const 8)) (i64.const 3)) 112 | ) 113 | 114 | (func "effects" $fx (result i32) 115 | (local i32) 116 | (block 117 | (set_local 0 (i32.const 1)) 118 | (set_local 0 (i32.mul (get_local 0) (i32.const 3))) 119 | (set_local 0 (i32.sub (get_local 0) (i32.const 5))) 120 | (set_local 0 (i32.mul (get_local 0) (i32.const 7))) 121 | (br 0) 122 | (set_local 0 (i32.mul (get_local 0) (i32.const 100))) 123 | ) 124 | (i32.eq (get_local 0) (i32.const -14)) 125 | ) 126 | ) 127 | 128 | (assert_return (invoke "empty")) 129 | (assert_return (invoke "singular") (i32.const 7)) 130 | (assert_return (invoke "multi") (i32.const 8)) 131 | (assert_return (invoke "nested") (i32.const 9)) 132 | (assert_return (invoke "deep") (i32.const 150)) 133 | 134 | (assert_return (invoke "as-unary-operand") (i32.const 0)) 135 | (assert_return (invoke "as-binary-operand") (i32.const 12)) 136 | (assert_return (invoke "as-test-operand") (i32.const 0)) 137 | (assert_return (invoke "as-compare-operand") (i32.const 0)) 138 | 139 | (assert_return (invoke "break-bare") (i32.const 19)) 140 | (assert_return (invoke "break-value") (i32.const 18)) 141 | (assert_return (invoke "break-repeated") (i32.const 18)) 142 | (assert_return (invoke "break-inner") (i32.const 0xf)) 143 | 144 | (assert_return (invoke "drop-mid") (i32.const 8)) 145 | (assert_return (invoke "drop-last")) 146 | (assert_return (invoke "drop-break-void")) 147 | (assert_return (invoke "drop-break-value")) 148 | (assert_return (invoke "drop-break-value-heterogeneous")) 149 | 150 | (assert_return (invoke "effects") (i32.const 1)) 151 | 152 | (assert_invalid 153 | (module (func $type-empty-i32 (result i32) (block))) 154 | "type mismatch" 155 | ) 156 | (assert_invalid 157 | (module (func $type-empty-i64 (result i64) (block))) 158 | "type mismatch" 159 | ) 160 | (assert_invalid 161 | (module (func $type-empty-f32 (result f32) (block))) 162 | "type mismatch" 163 | ) 164 | (assert_invalid 165 | (module (func $type-empty-f64 (result f64) (block))) 166 | "type mismatch" 167 | ) 168 | 169 | (assert_invalid 170 | (module (func $type-value-void-vs-num (result i32) 171 | (block (nop)) 172 | )) 173 | "type mismatch" 174 | ) 175 | (assert_invalid 176 | (module (func $type-value-num-vs-num (result i32) 177 | (block (f32.const 0)) 178 | )) 179 | "type mismatch" 180 | ) 181 | (assert_invalid 182 | (module (func $type-value-void-vs-num-after-break (result i32) 183 | (block (br 0 (i32.const 1)) (nop)) 184 | )) 185 | "type mismatch" 186 | ) 187 | (assert_invalid 188 | (module (func $type-value-num-vs-num-after-break (result i32) 189 | (block (br 0 (i32.const 1)) (f32.const 0)) 190 | )) 191 | "type mismatch" 192 | ) 193 | 194 | (assert_invalid 195 | (module (func $type-break-last-void-vs-num (result i32) 196 | (block (br 0)) 197 | )) 198 | "type mismatch" 199 | ) 200 | (assert_invalid 201 | (module (func $type-break-void-vs-num (result i32) 202 | (block (br 0) (i32.const 1)) 203 | )) 204 | "type mismatch" 205 | ) 206 | (assert_invalid 207 | (module (func $type-break-num-vs-num (result i32) 208 | (block (br 0 (i64.const 1)) (i32.const 1)) 209 | )) 210 | "type mismatch" 211 | ) 212 | (assert_invalid 213 | (module (func $type-break-first-num-vs-num (result i32) 214 | (block (br 0 (i64.const 1)) (br 0 (i32.const 1))) 215 | )) 216 | "type mismatch" 217 | ) 218 | (assert_invalid 219 | (module (func $type-break-second-num-vs-num (result i32) 220 | (block (br 0 (i32.const 1)) (br 0 (f64.const 1))) 221 | )) 222 | "type mismatch" 223 | ) 224 | 225 | (assert_invalid 226 | (module (func $type-break-nested-void-vs-num (result i32) 227 | (block (block (br 1)) (br 0 (i32.const 1))) 228 | )) 229 | "type mismatch" 230 | ) 231 | (assert_invalid 232 | (module (func $type-break-nested-num-vs-num (result i32) 233 | (block (block (br 1 (i64.const 1))) (br 0 (i32.const 1))) 234 | )) 235 | "type mismatch" 236 | ) 237 | (assert_invalid 238 | (module (func $type-break-operand-void-vs-num (result i32) 239 | (i32.ctz (block (br 0))) 240 | )) 241 | "type mismatch" 242 | ) 243 | (assert_invalid 244 | (module (func $type-break-operand-num-vs-num (result i32) 245 | (i64.ctz (block (br 0 (i64.const 9)))) 246 | )) 247 | "type mismatch" 248 | ) 249 | (assert_invalid 250 | (module (func (result i32) (block (br 0)))) 251 | "type mismatch" 252 | ) 253 | (assert_invalid 254 | (module (func (result i32) (i32.ctz (block (br 0))))) 255 | "type mismatch" 256 | ) 257 | 258 | -------------------------------------------------------------------------------- /test/br.wast: -------------------------------------------------------------------------------- 1 | ;; Test `br` operator 2 | 3 | (module 4 | (func "type-i32" (block (i32.ctz (br 0)))) 5 | (func "type-i64" (block (i64.ctz (br 0)))) 6 | (func "type-f32" (block (f32.neg (br 0)))) 7 | (func "type-f64" (block (f64.neg (br 0)))) 8 | 9 | (func "type-i32-value" (result i32) (block (i32.ctz (br 0 (i32.const 1))))) 10 | (func "type-i64-value" (result i64) (block (i64.ctz (br 0 (i64.const 2))))) 11 | (func "type-f32-value" (result f32) (block (f32.neg (br 0 (f32.const 3))))) 12 | (func "type-f64-value" (result f64) (block (f64.neg (br 0 (f64.const 4))))) 13 | 14 | (func "as-block-first" 15 | (block (br 0) (i32.const 2)) 16 | ) 17 | (func "as-block-mid" 18 | (block (i32.const 1) (br 0) (i32.const 2)) 19 | ) 20 | (func "as-block-last" 21 | (block (nop) (i32.const 1) (br 0)) 22 | ) 23 | (func "as-block-value" (result i32) 24 | (block (nop) (i32.const 1) (br 0 (i32.const 2))) 25 | ) 26 | 27 | (func "as-loop-first" (result i32) 28 | (loop (br 1 (i32.const 3)) (i32.const 2)) 29 | ) 30 | (func "as-loop-mid" (result i32) 31 | (loop (i32.const 1) (br 1 (i32.const 4)) (i32.const 2)) 32 | ) 33 | (func "as-loop-last" (result i32) 34 | (loop (nop) (i32.const 1) (br 1 (i32.const 5))) 35 | ) 36 | 37 | (func "as-br-value" (result i32) 38 | (block (br 0 (br 0 (i32.const 9)))) 39 | ) 40 | 41 | (func "as-br_if-cond" 42 | (block (br_if 0 (br 0))) 43 | ) 44 | (func "as-br_if-value" (result i32) 45 | (block (br_if 0 (br 0 (i32.const 8)) (i32.const 1)) (i32.const 7)) 46 | ) 47 | (func "as-br_if-value-cond" (result i32) 48 | (block (br_if 0 (i32.const 6) (br 0 (i32.const 9))) (i32.const 7)) 49 | ) 50 | 51 | (func "as-br_table-index" 52 | (block (br_table 0 0 0 (br 0))) 53 | ) 54 | (func "as-br_table-value" (result i32) 55 | (block (br_table 0 0 0 (br 0 (i32.const 10)) (i32.const 1)) (i32.const 7)) 56 | ) 57 | (func "as-br_table-value-index" (result i32) 58 | (block (br_table 0 0 (i32.const 6) (br 0 (i32.const 11))) (i32.const 7)) 59 | ) 60 | 61 | (func "as-return-value" (result i64) 62 | (block (return (br 0 (i64.const 7)))) 63 | ) 64 | 65 | (func "as-if-cond" (result i32) 66 | (block (if (br 0 (i32.const 2)) (i32.const 0) (i32.const 1))) 67 | ) 68 | (func "as-if-then" (param i32 i32) (result i32) 69 | (block (if (get_local 0) (br 1 (i32.const 3)) (get_local 1))) 70 | ) 71 | (func "as-if-else" (param i32 i32) (result i32) 72 | (block (if (get_local 0) (get_local 1) (br 1 (i32.const 4)))) 73 | ) 74 | 75 | (func "as-select-first" (param i32 i32) (result i32) 76 | (block (select (br 0 (i32.const 5)) (get_local 0) (get_local 1))) 77 | ) 78 | (func "as-select-second" (param i32 i32) (result i32) 79 | (block (select (get_local 0) (br 0 (i32.const 6)) (get_local 1))) 80 | ) 81 | (func "as-select-cond" (result i32) 82 | (block (select (i32.const 0) (i32.const 1) (br 0 (i32.const 7)))) 83 | ) 84 | 85 | (func $f (param i32 i32 i32) (result i32) (i32.const -1)) 86 | (func "as-call-first" (result i32) 87 | (block (call $f (br 0 (i32.const 12)) (i32.const 2) (i32.const 3))) 88 | ) 89 | (func "as-call-mid" (result i32) 90 | (block (call $f (i32.const 1) (br 0 (i32.const 13)) (i32.const 3))) 91 | ) 92 | (func "as-call-last" (result i32) 93 | (block (call $f (i32.const 1) (i32.const 2) (br 0 (i32.const 14)))) 94 | ) 95 | 96 | (import "spectest" "print" (param i32 i32 i32)) 97 | (func "as-call_import-first" 98 | (block (call_import 0 (br 0) (i32.const 2) (i32.const 3))) 99 | ) 100 | (func "as-call_import-mid" 101 | (block (call_import 0 (i32.const 1) (br 0) (i32.const 3))) 102 | ) 103 | (func "as-call_import-last" 104 | (block (call_import 0 (i32.const 1) (i32.const 2) (br 0))) 105 | ) 106 | 107 | (type $sig (func (param i32 i32 i32) (result i32))) 108 | (table $f) 109 | (func "as-call_indirect-func" (result i32) 110 | (block (call_indirect $sig (br 0 (i32.const 20)) (i32.const 1) (i32.const 2) (i32.const 3))) 111 | ) 112 | (func "as-call_indirect-first" (result i32) 113 | (block (call_indirect $sig (i32.const 0) (br 0 (i32.const 21)) (i32.const 2) (i32.const 3))) 114 | ) 115 | (func "as-call_indirect-mid" (result i32) 116 | (block (call_indirect $sig (i32.const 0) (i32.const 1) (br 0 (i32.const 22)) (i32.const 3))) 117 | ) 118 | (func "as-call_indirect-last" (result i32) 119 | (block (call_indirect $sig (i32.const 0) (i32.const 1) (i32.const 2) (br 0 (i32.const 23)))) 120 | ) 121 | 122 | (func "as-set_local-value" (result i32) (local f32) 123 | (block (set_local 0 (br 0 (i32.const 17))) (i32.const -1)) 124 | ) 125 | 126 | (memory 1) 127 | (func "as-load-address" (result f32) 128 | (block (f32.load (br 0 (f32.const 1.7)))) 129 | ) 130 | (func "as-loadN-address" (result i64) 131 | (block (i64.load8_s (br 0 (i64.const 30)))) 132 | ) 133 | 134 | (func "as-store-address" (result i32) 135 | (block (f64.store (br 0 (i32.const 30)) (f64.const 7)) (i32.const -1)) 136 | ) 137 | (func "as-store-value" (result i32) 138 | (block (i64.store (i32.const 2) (br 0 (i32.const 31))) (i32.const -1)) 139 | ) 140 | 141 | (func "as-storeN-address" (result i32) 142 | (block (i32.store8 (br 0 (i32.const 32)) (i32.const 7)) (i32.const -1)) 143 | ) 144 | (func "as-storeN-value" (result i32) 145 | (block (i64.store16 (i32.const 2) (br 0 (i32.const 33))) (i32.const -1)) 146 | ) 147 | 148 | (func "as-unary-operand" (result f32) 149 | (block (f32.neg (br 0 (f32.const 3.4)))) 150 | ) 151 | 152 | (func "as-binary-left" (result i32) 153 | (block (i32.add (br 0 (i32.const 3)) (i32.const 10))) 154 | ) 155 | (func "as-binary-right" (result i64) 156 | (block (i64.sub (i64.const 10) (br 0 (i64.const 45)))) 157 | ) 158 | 159 | (func "as-test-operand" (result i32) 160 | (block (i32.eqz (br 0 (i32.const 44)))) 161 | ) 162 | 163 | (func "as-compare-left" (result i32) 164 | (block (f64.le (br 0 (i32.const 43)) (f64.const 10))) 165 | ) 166 | (func "as-compare-right" (result i32) 167 | (block (f32.ne (f32.const 10) (br 0 (i32.const 42)))) 168 | ) 169 | 170 | (func "as-convert-operand" (result i32) 171 | (block (i32.wrap/i64 (br 0 (i32.const 41)))) 172 | ) 173 | 174 | (func "as-grow_memory-size" (result i32) 175 | (block (grow_memory (br 0 (i32.const 40)))) 176 | ) 177 | 178 | (func "nested-block-value" (result i32) 179 | (i32.add 180 | (i32.const 1) 181 | (block 182 | (i32.const 2) 183 | (i32.add (i32.const 4) (br 0 (i32.const 8))) 184 | ) 185 | ) 186 | ) 187 | 188 | (func "nested-br-value" (result i32) 189 | (i32.add 190 | (i32.const 1) 191 | (block 192 | (i32.const 2) 193 | (block 194 | (i32.const 4) 195 | (br 0 (br 1 (i32.const 8))) 196 | ) 197 | (i32.const 16) 198 | ) 199 | ) 200 | ) 201 | 202 | (func "nested-br_if-value" (result i32) 203 | (i32.add 204 | (i32.const 1) 205 | (block 206 | (i32.const 2) 207 | (block 208 | (i32.const 4) 209 | (br_if 0 (br 1 (i32.const 8)) (i32.const 1)) 210 | ) 211 | (i32.const 16) 212 | ) 213 | ) 214 | ) 215 | 216 | (func "nested-br_if-value-cond" (result i32) 217 | (i32.add 218 | (i32.const 1) 219 | (block 220 | (i32.const 2) 221 | (br_if 0 (i32.const 4) (br 0 (i32.const 8))) 222 | (i32.const 16) 223 | ) 224 | ) 225 | ) 226 | 227 | (func "nested-br_table-value" (result i32) 228 | (i32.add 229 | (i32.const 1) 230 | (block 231 | (i32.const 2) 232 | (block 233 | (i32.const 4) 234 | (br_table 0 (br 1 (i32.const 8)) (i32.const 1)) 235 | ) 236 | (i32.const 16) 237 | ) 238 | ) 239 | ) 240 | 241 | (func "nested-br_table-value-index" (result i32) 242 | (i32.add 243 | (i32.const 1) 244 | (block 245 | (i32.const 2) 246 | (br_table 0 (i32.const 4) (br 0 (i32.const 8))) 247 | (i32.const 16) 248 | ) 249 | ) 250 | ) 251 | ) 252 | 253 | (assert_return (invoke "type-i32")) 254 | (assert_return (invoke "type-i64")) 255 | (assert_return (invoke "type-f32")) 256 | (assert_return (invoke "type-f64")) 257 | 258 | (assert_return (invoke "type-i32-value") (i32.const 1)) 259 | (assert_return (invoke "type-i64-value") (i64.const 2)) 260 | (assert_return (invoke "type-f32-value") (f32.const 3)) 261 | (assert_return (invoke "type-f64-value") (f64.const 4)) 262 | 263 | (assert_return (invoke "as-block-first")) 264 | (assert_return (invoke "as-block-mid")) 265 | (assert_return (invoke "as-block-last")) 266 | (assert_return (invoke "as-block-value") (i32.const 2)) 267 | 268 | (assert_return (invoke "as-loop-first") (i32.const 3)) 269 | (assert_return (invoke "as-loop-mid") (i32.const 4)) 270 | (assert_return (invoke "as-loop-last") (i32.const 5)) 271 | 272 | (assert_return (invoke "as-br-value") (i32.const 9)) 273 | 274 | (assert_return (invoke "as-br_if-cond")) 275 | (assert_return (invoke "as-br_if-value") (i32.const 8)) 276 | (assert_return (invoke "as-br_if-value-cond") (i32.const 9)) 277 | 278 | (assert_return (invoke "as-br_table-index")) 279 | (assert_return (invoke "as-br_table-value") (i32.const 10)) 280 | (assert_return (invoke "as-br_table-value-index") (i32.const 11)) 281 | 282 | (assert_return (invoke "as-return-value") (i64.const 7)) 283 | 284 | (assert_return (invoke "as-if-cond") (i32.const 2)) 285 | (assert_return (invoke "as-if-then" (i32.const 1) (i32.const 6)) (i32.const 3)) 286 | (assert_return (invoke "as-if-then" (i32.const 0) (i32.const 6)) (i32.const 6)) 287 | (assert_return (invoke "as-if-else" (i32.const 0) (i32.const 6)) (i32.const 4)) 288 | (assert_return (invoke "as-if-else" (i32.const 1) (i32.const 6)) (i32.const 6)) 289 | 290 | (assert_return (invoke "as-select-first" (i32.const 0) (i32.const 6)) (i32.const 5)) 291 | (assert_return (invoke "as-select-first" (i32.const 1) (i32.const 6)) (i32.const 5)) 292 | (assert_return (invoke "as-select-second" (i32.const 0) (i32.const 6)) (i32.const 6)) 293 | (assert_return (invoke "as-select-second" (i32.const 1) (i32.const 6)) (i32.const 6)) 294 | (assert_return (invoke "as-select-cond") (i32.const 7)) 295 | 296 | (assert_return (invoke "as-call-first") (i32.const 12)) 297 | (assert_return (invoke "as-call-mid") (i32.const 13)) 298 | (assert_return (invoke "as-call-last") (i32.const 14)) 299 | 300 | (assert_return (invoke "as-call_import-first")) 301 | (assert_return (invoke "as-call_import-mid")) 302 | (assert_return (invoke "as-call_import-last")) 303 | 304 | (assert_return (invoke "as-call_indirect-func") (i32.const 20)) 305 | (assert_return (invoke "as-call_indirect-first") (i32.const 21)) 306 | (assert_return (invoke "as-call_indirect-mid") (i32.const 22)) 307 | (assert_return (invoke "as-call_indirect-last") (i32.const 23)) 308 | 309 | (assert_return (invoke "as-set_local-value") (i32.const 17)) 310 | 311 | (assert_return (invoke "as-load-address") (f32.const 1.7)) 312 | (assert_return (invoke "as-loadN-address") (i64.const 30)) 313 | 314 | (assert_return (invoke "as-store-address") (i32.const 30)) 315 | (assert_return (invoke "as-store-value") (i32.const 31)) 316 | (assert_return (invoke "as-storeN-address") (i32.const 32)) 317 | (assert_return (invoke "as-storeN-value") (i32.const 33)) 318 | 319 | (assert_return (invoke "as-unary-operand") (f32.const 3.4)) 320 | 321 | (assert_return (invoke "as-binary-left") (i32.const 3)) 322 | (assert_return (invoke "as-binary-right") (i64.const 45)) 323 | 324 | (assert_return (invoke "as-test-operand") (i32.const 44)) 325 | 326 | (assert_return (invoke "as-compare-left") (i32.const 43)) 327 | (assert_return (invoke "as-compare-right") (i32.const 42)) 328 | 329 | (assert_return (invoke "as-convert-operand") (i32.const 41)) 330 | 331 | (assert_return (invoke "as-grow_memory-size") (i32.const 40)) 332 | 333 | (assert_return (invoke "nested-block-value") (i32.const 9)) 334 | (assert_return (invoke "nested-br-value") (i32.const 9)) 335 | (assert_return (invoke "nested-br_if-value") (i32.const 9)) 336 | (assert_return (invoke "nested-br_if-value-cond") (i32.const 9)) 337 | (assert_return (invoke "nested-br_table-value") (i32.const 9)) 338 | (assert_return (invoke "nested-br_table-value-index") (i32.const 9)) 339 | 340 | (assert_invalid 341 | (module (func $type-arg-void-vs-num (result i32) 342 | (block (br 0) (i32.const 1)) 343 | )) 344 | "type mismatch" 345 | ) 346 | (assert_invalid 347 | (module (func $type-arg-num-vs-num (result i32) 348 | (block (br 0 (i64.const 1)) (i32.const 1)) 349 | )) 350 | "type mismatch" 351 | ) 352 | 353 | (assert_invalid 354 | (module (func $unbound-label (br 1))) 355 | "unknown label" 356 | ) 357 | (assert_invalid 358 | (module (func $unbound-nested-label (block (block (br 5))))) 359 | "unknown label" 360 | ) 361 | (assert_invalid 362 | (module (func $large-label (br 0x100000001))) 363 | "unknown label" 364 | ) 365 | -------------------------------------------------------------------------------- /test/br_if.wast: -------------------------------------------------------------------------------- 1 | ;; Test `br_if` operator 2 | 3 | (module 4 | (func $dummy) 5 | 6 | (func "as-block-first" (param i32) (result i32) 7 | (block (br_if 0 (get_local 0)) (return (i32.const 2))) (i32.const 3) 8 | ) 9 | (func "as-block-mid" (param i32) (result i32) 10 | (block (call $dummy) (br_if 0 (get_local 0)) (return (i32.const 2))) (i32.const 3) 11 | ) 12 | (func "as-block-last" (param i32) 13 | (block (call $dummy) (call $dummy) (br_if 0 (get_local 0))) 14 | ) 15 | (func "as-block-first-value" (param i32) (result i32) 16 | (block (br_if 0 (i32.const 10) (get_local 0)) (i32.const 11)) 17 | ) 18 | (func "as-block-mid-value" (param i32) (result i32) 19 | (block (call $dummy) (br_if 0 (i32.const 20) (get_local 0)) (i32.const 21)) 20 | ) 21 | 22 | (func "as-loop-first" (param i32) (result i32) 23 | (loop (br_if 1 (i32.const 3) (get_local 0)) (i32.const 2)) 24 | ) 25 | (func "as-loop-mid" (param i32) (result i32) 26 | (loop (call $dummy) (br_if 1 (i32.const 4) (get_local 0)) (i32.const 2)) 27 | ) 28 | (func "as-loop-last" (param i32) 29 | (loop (call $dummy) (br_if 1 (get_local 0))) 30 | ) 31 | 32 | (func "as-br-value" (param i32) 33 | (block (br 0 (br_if 0 (get_local 0)))) 34 | ) 35 | (func "as-br_if-value" (param i32 i32) 36 | (block (br_if 0 (br_if 0 (get_local 0)) (get_local 1))) 37 | ) 38 | (func "as-br_table-value" (param i32 i32) 39 | (block (br_table 0 0 0 (br_if 0 (get_local 0)) (get_local 1))) 40 | ) 41 | 42 | (func "as-return-value" (param i32) 43 | (block (return (br_if 0 (get_local 0)))) 44 | ) 45 | 46 | (func "as-if-then" (param i32 i32) 47 | (block (if (get_local 0) (br_if 1 (i32.const 3) (get_local 1)) (call $dummy))) 48 | ) 49 | (func "as-if-else" (param i32 i32) 50 | (block (if (get_local 0) (call $dummy) (br_if 1 (i32.const 4) (get_local 1)))) 51 | ) 52 | 53 | (func "nested-block-value" (param i32) (result i32) 54 | (i32.add 55 | (i32.const 1) 56 | (block 57 | (i32.const 2) 58 | (i32.add 59 | (i32.const 4) 60 | (block (br_if 1 (i32.const 8) (get_local 0)) (i32.const 16)) 61 | ) 62 | ) 63 | ) 64 | ) 65 | 66 | (func "nested-br-value" (param i32) (result i32) 67 | (i32.add 68 | (i32.const 1) 69 | (block 70 | (i32.const 2) 71 | (br 0 72 | (block (br_if 1 (i32.const 8) (get_local 0)) (i32.const 4)) 73 | ) 74 | (i32.const 16) 75 | ) 76 | ) 77 | ) 78 | 79 | (func "nested-br_if-value" (param i32) (result i32) 80 | (i32.add 81 | (i32.const 1) 82 | (block 83 | (i32.const 2) 84 | (br_if 0 85 | (block (br_if 1 (i32.const 8) (get_local 0)) (i32.const 4)) 86 | (i32.const 1) 87 | ) 88 | (i32.const 16) 89 | ) 90 | ) 91 | ) 92 | 93 | (func "nested-br_if-value-cond" (param i32) (result i32) 94 | (i32.add 95 | (i32.const 1) 96 | (block 97 | (i32.const 2) 98 | (br_if 0 99 | (i32.const 4) 100 | (block (br_if 1 (i32.const 8) (get_local 0)) (i32.const 1)) 101 | ) 102 | (i32.const 16) 103 | ) 104 | ) 105 | ) 106 | 107 | (func "nested-br_table-value" (param i32) (result i32) 108 | (i32.add 109 | (i32.const 1) 110 | (block 111 | (i32.const 2) 112 | (br_table 0 113 | (block (br_if 1 (i32.const 8) (get_local 0)) (i32.const 4)) 114 | (i32.const 1) 115 | ) 116 | (i32.const 16) 117 | ) 118 | ) 119 | ) 120 | 121 | (func "nested-br_table-value-index" (param i32) (result i32) 122 | (i32.add 123 | (i32.const 1) 124 | (block 125 | (i32.const 2) 126 | (br_table 0 127 | (i32.const 4) 128 | (block (br_if 1 (i32.const 8) (get_local 0)) (i32.const 1)) 129 | ) 130 | (i32.const 16) 131 | ) 132 | ) 133 | ) 134 | ) 135 | 136 | (assert_return (invoke "as-block-first" (i32.const 0)) (i32.const 2)) 137 | (assert_return (invoke "as-block-first" (i32.const 1)) (i32.const 3)) 138 | (assert_return (invoke "as-block-mid" (i32.const 0)) (i32.const 2)) 139 | (assert_return (invoke "as-block-mid" (i32.const 1)) (i32.const 3)) 140 | (assert_return (invoke "as-block-last" (i32.const 0))) 141 | (assert_return (invoke "as-block-last" (i32.const 1))) 142 | 143 | (assert_return (invoke "as-block-first-value" (i32.const 0)) (i32.const 11)) 144 | (assert_return (invoke "as-block-first-value" (i32.const 1)) (i32.const 10)) 145 | (assert_return (invoke "as-block-mid-value" (i32.const 0)) (i32.const 21)) 146 | (assert_return (invoke "as-block-mid-value" (i32.const 1)) (i32.const 20)) 147 | 148 | (assert_return (invoke "as-loop-first" (i32.const 0)) (i32.const 2)) 149 | (assert_return (invoke "as-loop-first" (i32.const 1)) (i32.const 3)) 150 | (assert_return (invoke "as-loop-mid" (i32.const 0)) (i32.const 2)) 151 | (assert_return (invoke "as-loop-mid" (i32.const 1)) (i32.const 4)) 152 | (assert_return (invoke "as-loop-last" (i32.const 0))) 153 | (assert_return (invoke "as-loop-last" (i32.const 1))) 154 | 155 | (assert_return (invoke "as-br-value" (i32.const 0))) 156 | (assert_return (invoke "as-br-value" (i32.const 1))) 157 | 158 | (assert_return (invoke "as-br_if-value" (i32.const 0) (i32.const 0))) 159 | (assert_return (invoke "as-br_if-value" (i32.const 1) (i32.const 0))) 160 | (assert_return (invoke "as-br_if-value" (i32.const 0) (i32.const 1))) 161 | (assert_return (invoke "as-br_if-value" (i32.const 1) (i32.const 1))) 162 | 163 | (assert_return (invoke "as-br_table-value" (i32.const 0) (i32.const 0))) 164 | (assert_return (invoke "as-br_table-value" (i32.const 1) (i32.const 0))) 165 | (assert_return (invoke "as-br_table-value" (i32.const 10) (i32.const 0))) 166 | (assert_return (invoke "as-br_table-value" (i32.const 0) (i32.const 1))) 167 | (assert_return (invoke "as-br_table-value" (i32.const 1) (i32.const 1))) 168 | (assert_return (invoke "as-br_table-value" (i32.const 10) (i32.const 1))) 169 | 170 | (assert_return (invoke "as-return-value" (i32.const 0))) 171 | (assert_return (invoke "as-return-value" (i32.const 1))) 172 | 173 | (assert_return (invoke "as-if-then" (i32.const 0) (i32.const 0))) 174 | (assert_return (invoke "as-if-then" (i32.const 4) (i32.const 0))) 175 | (assert_return (invoke "as-if-then" (i32.const 0) (i32.const 1))) 176 | (assert_return (invoke "as-if-then" (i32.const 4) (i32.const 1))) 177 | (assert_return (invoke "as-if-else" (i32.const 0) (i32.const 0))) 178 | (assert_return (invoke "as-if-else" (i32.const 3) (i32.const 0))) 179 | (assert_return (invoke "as-if-else" (i32.const 0) (i32.const 1))) 180 | (assert_return (invoke "as-if-else" (i32.const 3) (i32.const 1))) 181 | 182 | (assert_return (invoke "nested-block-value" (i32.const 0)) (i32.const 21)) 183 | (assert_return (invoke "nested-block-value" (i32.const 1)) (i32.const 9)) 184 | (assert_return (invoke "nested-br-value" (i32.const 0)) (i32.const 5)) 185 | (assert_return (invoke "nested-br-value" (i32.const 1)) (i32.const 9)) 186 | (assert_return (invoke "nested-br_if-value" (i32.const 0)) (i32.const 5)) 187 | (assert_return (invoke "nested-br_if-value" (i32.const 1)) (i32.const 9)) 188 | (assert_return (invoke "nested-br_if-value-cond" (i32.const 0)) (i32.const 5)) 189 | (assert_return (invoke "nested-br_if-value-cond" (i32.const 1)) (i32.const 9)) 190 | (assert_return (invoke "nested-br_table-value" (i32.const 0)) (i32.const 5)) 191 | (assert_return (invoke "nested-br_table-value" (i32.const 1)) (i32.const 9)) 192 | (assert_return (invoke "nested-br_table-value-index" (i32.const 0)) (i32.const 5)) 193 | (assert_return (invoke "nested-br_table-value-index" (i32.const 1)) (i32.const 9)) 194 | 195 | (assert_invalid 196 | (module (func $type-false-i32 (block (i32.ctz (br_if 0 (i32.const 0)))))) 197 | "type mismatch" 198 | ) 199 | (assert_invalid 200 | (module (func $type-false-i64 (block (i64.ctz (br_if 0 (i32.const 0)))))) 201 | "type mismatch" 202 | ) 203 | (assert_invalid 204 | (module (func $type-false-f32 (block (f32.neg (br_if 0 (i32.const 0)))))) 205 | "type mismatch" 206 | ) 207 | (assert_invalid 208 | (module (func $type-false-f64 (block (f64.neg (br_if 0 (i32.const 0)))))) 209 | "type mismatch" 210 | ) 211 | 212 | (assert_invalid 213 | (module (func $type-true-i32 (block (i32.ctz (br_if 0 (i32.const 1)))))) 214 | "type mismatch" 215 | ) 216 | (assert_invalid 217 | (module (func $type-true-i64 (block (i64.ctz (br_if 0 (i64.const 1)))))) 218 | "type mismatch" 219 | ) 220 | (assert_invalid 221 | (module (func $type-true-f32 (block (f32.neg (br_if 0 (f32.const 1)))))) 222 | "type mismatch" 223 | ) 224 | (assert_invalid 225 | (module (func $type-true-f64 (block (f64.neg (br_if 0 (i64.const 1)))))) 226 | "type mismatch" 227 | ) 228 | 229 | (assert_invalid 230 | (module (func $type-false-arg-void-vs-num (result i32) 231 | (block (br_if 0 (i32.const 0)) (i32.const 1)) 232 | )) 233 | "type mismatch" 234 | ) 235 | (assert_invalid 236 | (module (func $type-true-arg-void-vs-num (result i32) 237 | (block (br_if 0 (i32.const 1)) (i32.const 1)) 238 | )) 239 | "type mismatch" 240 | ) 241 | (assert_invalid 242 | (module (func $type-false-arg-num-vs-num (result i32) 243 | (block (br_if 0 (i64.const 1) (i32.const 0)) (i32.const 1)) 244 | )) 245 | "type mismatch" 246 | ) 247 | (assert_invalid 248 | (module (func $type-true-arg-num-vs-num (result i32) 249 | (block (br_if 0 (i64.const 1) (i32.const 0)) (i32.const 1)) 250 | )) 251 | "type mismatch" 252 | ) 253 | 254 | (assert_invalid 255 | (module (func $type-cond-void-vs-i32 256 | (block (br_if 0 (nop))) 257 | )) 258 | "type mismatch" 259 | ) 260 | (assert_invalid 261 | (module (func $type-cond-num-vs-i32 262 | (block (br_if 0 (i64.const 0))) 263 | )) 264 | "type mismatch" 265 | ) 266 | (assert_invalid 267 | (module (func $type-arg-cond-void-vs-i32 (result i32) 268 | (block (br_if 0 (i32.const 0) (nop)) (i32.const 1)) 269 | )) 270 | "type mismatch" 271 | ) 272 | (assert_invalid 273 | (module (func $type-arg-cond-num-vs-i32 (result i32) 274 | (block (br_if 0 (i32.const 0) (i64.const 0)) (i32.const 1)) 275 | )) 276 | "type mismatch" 277 | ) 278 | 279 | (assert_invalid 280 | (module (func $unbound-label (br_if 1 (i32.const 1)))) 281 | "unknown label" 282 | ) 283 | (assert_invalid 284 | (module (func $unbound-nested-label (block (block (br_if 5 (i32.const 1)))))) 285 | "unknown label" 286 | ) 287 | (assert_invalid 288 | (module (func $large-label (br_if 0x100000001 (i32.const 1)))) 289 | "unknown label" 290 | ) 291 | 292 | -------------------------------------------------------------------------------- /test/break-drop.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func $br (block (br 0))) 3 | (export "br" $br) 4 | 5 | (func $br-nop (block (br 0 (nop)))) 6 | (export "br-nop" $br-nop) 7 | 8 | (func $br-drop (block (br 0 (i32.const 1)))) 9 | (export "br-drop" $br-drop) 10 | 11 | (func $br-block-nop (block (br 0 (block (i32.const 1) (nop))))) 12 | (export "br-block-nop" $br-block-nop) 13 | 14 | (func $br-block-drop (block (br 0 (block (nop) (i32.const 1))))) 15 | (export "br-block-drop" $br-block-drop) 16 | 17 | (func $br_if (block (br_if 0 (i32.const 1)))) 18 | (export "br_if" $br_if) 19 | 20 | (func $br_if-nop (block (br_if 0 (nop) (i32.const 1)))) 21 | (export "br_if-nop" $br_if-nop) 22 | 23 | (func $br_if-drop (block (br_if 0 (i32.const 1) (i32.const 1)))) 24 | (export "br_if-drop" $br_if-drop) 25 | 26 | (func $br_if-block-nop (block (br_if 0 (block (i32.const 1) (nop)) (i32.const 1)))) 27 | (export "br_if-block-nop" $br_if-block-nop) 28 | 29 | (func $br_if-block-drop (block (br_if 0 (block (nop) (i32.const 1)) (i32.const 1)))) 30 | (export "br_if-block-drop" $br_if-block-drop) 31 | 32 | (func $br_table (block (br_table 0 (i32.const 0)))) 33 | (export "br_table" $br_table) 34 | 35 | (func $br_table-nop (block (br_table 0 (nop) (i32.const 0)))) 36 | (export "br_table-nop" $br_table-nop) 37 | 38 | (func $br_table-drop (block (br_table 0 (i32.const 1) (i32.const 0)))) 39 | (export "br_table-drop" $br_table-drop) 40 | 41 | (func $br_table-block-nop (block (br_table 0 (block (i32.const 1) (nop)) (i32.const 0)))) 42 | (export "br_table-block-nop" $br_table-block-nop) 43 | 44 | (func $br_table-block-drop (block (br_table 0 (block (nop) (i32.const 1)) (i32.const 0)))) 45 | (export "br_table-block-drop" $br_table-block-drop) 46 | ) 47 | 48 | (assert_return (invoke "br")) 49 | (assert_return (invoke "br-nop")) 50 | (assert_return (invoke "br-drop")) 51 | (assert_return (invoke "br-block-nop")) 52 | (assert_return (invoke "br-block-drop")) 53 | 54 | (assert_return (invoke "br_if")) 55 | (assert_return (invoke "br_if-nop")) 56 | (assert_return (invoke "br_if-drop")) 57 | (assert_return (invoke "br_if-block-nop")) 58 | (assert_return (invoke "br_if-block-drop")) 59 | 60 | (assert_return (invoke "br_table")) 61 | (assert_return (invoke "br_table-nop")) 62 | (assert_return (invoke "br_table-drop")) 63 | (assert_return (invoke "br_table-block-nop")) 64 | (assert_return (invoke "br_table-block-drop")) 65 | -------------------------------------------------------------------------------- /test/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 "type-i32" (result i32) (call $const-i32)) 23 | (func "type-i64" (result i64) (call $const-i64)) 24 | (func "type-f32" (result f32) (call $const-f32)) 25 | (func "type-f64" (result f64) (call $const-f64)) 26 | 27 | (func "type-first-i32" (result i32) (call $id-i32 (i32.const 32))) 28 | (func "type-first-i64" (result i64) (call $id-i64 (i64.const 64))) 29 | (func "type-first-f32" (result f32) (call $id-f32 (f32.const 1.32))) 30 | (func "type-first-f64" (result f64) (call $id-f64 (f64.const 1.64))) 31 | 32 | (func "type-second-i32" (result i32) 33 | (call $f32-i32 (f32.const 32.1) (i32.const 32)) 34 | ) 35 | (func "type-second-i64" (result i64) 36 | (call $i32-i64 (i32.const 32) (i64.const 64)) 37 | ) 38 | (func "type-second-f32" (result f32) 39 | (call $f64-f32 (f64.const 64) (f32.const 32)) 40 | ) 41 | (func "type-second-f64" (result f64) 42 | (call $i64-f64 (i64.const 64) (f64.const 64.1)) 43 | ) 44 | 45 | ;; Recursion 46 | 47 | (func "fac" $fac (param i64) (result i64) 48 | (if (i64.eqz (get_local 0)) 49 | (i64.const 1) 50 | (i64.mul (get_local 0) (call $fac (i64.sub (get_local 0) (i64.const 1)))) 51 | ) 52 | ) 53 | 54 | (func "fac-acc" $fac-acc (param i64 i64) (result i64) 55 | (if (i64.eqz (get_local 0)) 56 | (get_local 1) 57 | (call $fac-acc 58 | (i64.sub (get_local 0) (i64.const 1)) 59 | (i64.mul (get_local 0) (get_local 1)) 60 | ) 61 | ) 62 | ) 63 | 64 | (func "fib" $fib (param i64) (result i64) 65 | (if (i64.le_u (get_local 0) (i64.const 1)) 66 | (i64.const 1) 67 | (i64.add 68 | (call $fib (i64.sub (get_local 0) (i64.const 2))) 69 | (call $fib (i64.sub (get_local 0) (i64.const 1))) 70 | ) 71 | ) 72 | ) 73 | 74 | (func "even" $even (param i64) (result i32) 75 | (if (i64.eqz (get_local 0)) 76 | (i32.const 44) 77 | (call $odd (i64.sub (get_local 0) (i64.const 1))) 78 | ) 79 | ) 80 | (func "odd" $odd (param i64) (result i32) 81 | (if (i64.eqz (get_local 0)) 82 | (i32.const 99) 83 | (call $even (i64.sub (get_local 0) (i64.const 1))) 84 | ) 85 | ) 86 | 87 | ;; Stack exhaustion 88 | 89 | ;; Implementations are required to have every call consume some abstract 90 | ;; resource towards exhausting some abstract finite limit, such that 91 | ;; infinitely recursive test cases reliably trap in finite time. This is 92 | ;; because otherwise applications could come to depend on it on those 93 | ;; implementations and be incompatible with implementations that don't do 94 | ;; it (or don't do it under the same circumstances). 95 | 96 | (func "runaway" $runaway (call $runaway)) 97 | 98 | (func "mutual-runaway" $mutual-runaway1 (call $mutual-runaway2)) 99 | (func $mutual-runaway2 (call $mutual-runaway1)) 100 | ) 101 | 102 | (assert_return (invoke "type-i32") (i32.const 0x132)) 103 | (assert_return (invoke "type-i64") (i64.const 0x164)) 104 | (assert_return (invoke "type-f32") (f32.const 0xf32)) 105 | (assert_return (invoke "type-f64") (f64.const 0xf64)) 106 | 107 | (assert_return (invoke "type-first-i32") (i32.const 32)) 108 | (assert_return (invoke "type-first-i64") (i64.const 64)) 109 | (assert_return (invoke "type-first-f32") (f32.const 1.32)) 110 | (assert_return (invoke "type-first-f64") (f64.const 1.64)) 111 | 112 | (assert_return (invoke "type-second-i32") (i32.const 32)) 113 | (assert_return (invoke "type-second-i64") (i64.const 64)) 114 | (assert_return (invoke "type-second-f32") (f32.const 32)) 115 | (assert_return (invoke "type-second-f64") (f64.const 64.1)) 116 | 117 | (assert_return (invoke "fac" (i64.const 0)) (i64.const 1)) 118 | (assert_return (invoke "fac" (i64.const 1)) (i64.const 1)) 119 | (assert_return (invoke "fac" (i64.const 5)) (i64.const 120)) 120 | (assert_return (invoke "fac" (i64.const 25)) (i64.const 7034535277573963776)) 121 | (assert_return (invoke "fac-acc" (i64.const 0) (i64.const 1)) (i64.const 1)) 122 | (assert_return (invoke "fac-acc" (i64.const 1) (i64.const 1)) (i64.const 1)) 123 | (assert_return (invoke "fac-acc" (i64.const 5) (i64.const 1)) (i64.const 120)) 124 | (assert_return 125 | (invoke "fac-acc" (i64.const 25) (i64.const 1)) 126 | (i64.const 7034535277573963776) 127 | ) 128 | 129 | (assert_return (invoke "fib" (i64.const 0)) (i64.const 1)) 130 | (assert_return (invoke "fib" (i64.const 1)) (i64.const 1)) 131 | (assert_return (invoke "fib" (i64.const 2)) (i64.const 2)) 132 | (assert_return (invoke "fib" (i64.const 5)) (i64.const 8)) 133 | (assert_return (invoke "fib" (i64.const 20)) (i64.const 10946)) 134 | 135 | (assert_return (invoke "even" (i64.const 0)) (i32.const 44)) 136 | (assert_return (invoke "even" (i64.const 1)) (i32.const 99)) 137 | (assert_return (invoke "even" (i64.const 100)) (i32.const 44)) 138 | (assert_return (invoke "even" (i64.const 77)) (i32.const 99)) 139 | (assert_return (invoke "odd" (i64.const 0)) (i32.const 99)) 140 | (assert_return (invoke "odd" (i64.const 1)) (i32.const 44)) 141 | (assert_return (invoke "odd" (i64.const 200)) (i32.const 99)) 142 | (assert_return (invoke "odd" (i64.const 77)) (i32.const 44)) 143 | 144 | (assert_trap (invoke "runaway") "call stack exhausted") 145 | (assert_trap (invoke "mutual-runaway") "call stack exhausted") 146 | 147 | 148 | ;; Invalid typing 149 | 150 | (assert_invalid 151 | (module 152 | (func $type-void-vs-num (i32.eqz (call 1))) 153 | (func) 154 | ) 155 | "type mismatch" 156 | ) 157 | (assert_invalid 158 | (module 159 | (func $type-num-vs-num (i32.eqz (call 1))) 160 | (func (result i64) (i64.const 1)) 161 | ) 162 | "type mismatch" 163 | ) 164 | 165 | (assert_invalid 166 | (module 167 | (func $arity-0-vs-1 (call 1)) 168 | (func (param i32)) 169 | ) 170 | "arity mismatch" 171 | ) 172 | (assert_invalid 173 | (module 174 | (func $arity-0-vs-2 (call 1)) 175 | (func (param f64 i32)) 176 | ) 177 | "arity mismatch" 178 | ) 179 | (assert_invalid 180 | (module 181 | (func $arity-1-vs-0 (call 1 (i32.const 1))) 182 | (func) 183 | ) 184 | "arity mismatch" 185 | ) 186 | (assert_invalid 187 | (module 188 | (func $arity-2-vs-0 (call 1 (f64.const 2) (i32.const 1))) 189 | (func) 190 | ) 191 | "arity mismatch" 192 | ) 193 | 194 | (assert_invalid 195 | (module 196 | (func $arity-nop-first (call 1 (nop) (i32.const 1) (i32.const 2))) 197 | (func (param i32 i32)) 198 | ) 199 | "arity mismatch" 200 | ) 201 | (assert_invalid 202 | (module 203 | (func $arity-nop-mid (call 1 (i32.const 1) (nop) (i32.const 2))) 204 | (func (param i32 i32)) 205 | ) 206 | "arity mismatch" 207 | ) 208 | (assert_invalid 209 | (module 210 | (func $arity-nop-last (call 1 (i32.const 1) (i32.const 2) (nop))) 211 | (func (param i32 i32)) 212 | ) 213 | "arity mismatch" 214 | ) 215 | 216 | (assert_invalid 217 | (module 218 | (func $type-first-void-vs-num (call 1 (nop) (i32.const 1))) 219 | (func (param i32 i32)) 220 | ) 221 | "type mismatch" 222 | ) 223 | (assert_invalid 224 | (module 225 | (func $type-second-void-vs-num (call 1 (i32.const 1) (nop))) 226 | (func (param i32 i32)) 227 | ) 228 | "type mismatch" 229 | ) 230 | (assert_invalid 231 | (module 232 | (func $type-first-num-vs-num (call 1 (f64.const 1) (i32.const 1))) 233 | (func (param i32 f64)) 234 | ) 235 | "type mismatch" 236 | ) 237 | (assert_invalid 238 | (module 239 | (func $type-second-num-vs-num (call 1 (i32.const 1) (f64.const 1))) 240 | (func (param f64 i32)) 241 | ) 242 | "type mismatch" 243 | ) 244 | 245 | 246 | ;; Unbound function 247 | 248 | (assert_invalid 249 | (module (func $unbound-func (call 1))) 250 | "unknown function" 251 | ) 252 | (assert_invalid 253 | (module (func $large-func (call 10001232130000))) 254 | "unknown function" 255 | ) 256 | -------------------------------------------------------------------------------- /test/call_indirect.wast: -------------------------------------------------------------------------------- 1 | ;; Test `call_indirect` operator 2 | 3 | (module 4 | ;; Auxiliary definitions 5 | (type $proc (func)) 6 | (type $out-i32 (func (result i32))) 7 | (type $out-i64 (func (result i64))) 8 | (type $out-f32 (func (result f32))) 9 | (type $out-f64 (func (result f64))) 10 | (type $over-i32 (func (param i32) (result i32))) 11 | (type $over-i64 (func (param i64) (result i64))) 12 | (type $over-f32 (func (param f32) (result f32))) 13 | (type $over-f64 (func (param f64) (result f64))) 14 | (type $f32-i32 (func (param f32 i32) (result i32))) 15 | (type $i32-i64 (func (param i32 i64) (result i64))) 16 | (type $f64-f32 (func (param f64 f32) (result f32))) 17 | (type $i64-f64 (func (param i64 f64) (result f64))) 18 | 19 | (func $const-i32 (type $out-i32) (i32.const 0x132)) 20 | (func $const-i64 (type $out-i64) (i64.const 0x164)) 21 | (func $const-f32 (type $out-f32) (f32.const 0xf32)) 22 | (func $const-f64 (type $out-f64) (f64.const 0xf64)) 23 | 24 | (func $id-i32 (type $over-i32) (get_local 0)) 25 | (func $id-i64 (type $over-i64) (get_local 0)) 26 | (func $id-f32 (type $over-f32) (get_local 0)) 27 | (func $id-f64 (type $over-f64) (get_local 0)) 28 | 29 | (func $f32-i32 (type $f32-i32) (get_local 1)) 30 | (func $i32-i64 (type $i32-i64) (get_local 1)) 31 | (func $f64-f32 (type $f64-f32) (get_local 1)) 32 | (func $i64-f64 (type $i64-f64) (get_local 1)) 33 | 34 | (table 35 | $const-i32 $const-i64 $const-f32 $const-f64 36 | $id-i32 $id-i64 $id-f32 $id-f64 37 | $f32-i32 $i32-i64 $f64-f32 $i64-f64 38 | $fac $fib $even $odd 39 | $runaway $mutual-runaway1 $mutual-runaway2 40 | ) 41 | 42 | ;; Typing 43 | 44 | (func "type-i32" (result i32) (call_indirect $out-i32 (i32.const 0))) 45 | (func "type-i64" (result i64) (call_indirect $out-i64 (i32.const 1))) 46 | (func "type-f32" (result f32) (call_indirect $out-f32 (i32.const 2))) 47 | (func "type-f64" (result f64) (call_indirect $out-f64 (i32.const 3))) 48 | 49 | (func "type-index" (result i64) 50 | (call_indirect $over-i64 (i32.const 5) (i64.const 100)) 51 | ) 52 | 53 | (func "type-first-i32" (result i32) 54 | (call_indirect $over-i32 (i32.const 4) (i32.const 32)) 55 | ) 56 | (func "type-first-i64" (result i64) 57 | (call_indirect $over-i64 (i32.const 5) (i64.const 64)) 58 | ) 59 | (func "type-first-f32" (result f32) 60 | (call_indirect $over-f32 (i32.const 6) (f32.const 1.32)) 61 | ) 62 | (func "type-first-f64" (result f64) 63 | (call_indirect $over-f64 (i32.const 7) (f64.const 1.64)) 64 | ) 65 | 66 | (func "type-second-i32" (result i32) 67 | (call_indirect $f32-i32 (i32.const 8) (f32.const 32.1) (i32.const 32)) 68 | ) 69 | (func "type-second-i64" (result i64) 70 | (call_indirect $i32-i64 (i32.const 9) (i32.const 32) (i64.const 64)) 71 | ) 72 | (func "type-second-f32" (result f32) 73 | (call_indirect $f64-f32 (i32.const 10) (f64.const 64) (f32.const 32)) 74 | ) 75 | (func "type-second-f64" (result f64) 76 | (call_indirect $i64-f64 (i32.const 11) (i64.const 64) (f64.const 64.1)) 77 | ) 78 | 79 | ;; Dispatch 80 | 81 | (func "dispatch" (param i32 i64) (result i64) 82 | (call_indirect $over-i64 (get_local 0) (get_local 1)) 83 | ) 84 | 85 | ;; Recursion 86 | 87 | (func "fac" $fac (param i64) (result i64) 88 | (if (i64.eqz (get_local 0)) 89 | (i64.const 1) 90 | (i64.mul 91 | (get_local 0) 92 | (call_indirect $over-i64 (i32.const 12) 93 | (i64.sub (get_local 0) (i64.const 1)) 94 | ) 95 | ) 96 | ) 97 | ) 98 | 99 | (func "fib" $fib (param i64) (result i64) 100 | (if (i64.le_u (get_local 0) (i64.const 1)) 101 | (i64.const 1) 102 | (i64.add 103 | (call_indirect $over-i64 (i32.const 13) 104 | (i64.sub (get_local 0) (i64.const 2)) 105 | ) 106 | (call_indirect $over-i64 (i32.const 13) 107 | (i64.sub (get_local 0) (i64.const 1)) 108 | ) 109 | ) 110 | ) 111 | ) 112 | 113 | (func "even" $even (param i32) (result i32) 114 | (if (i32.eqz (get_local 0)) 115 | (i32.const 44) 116 | (call_indirect $over-i32 (i32.const 15) 117 | (i32.sub (get_local 0) (i32.const 1)) 118 | ) 119 | ) 120 | ) 121 | (func "odd" $odd (param i32) (result i32) 122 | (if (i32.eqz (get_local 0)) 123 | (i32.const 99) 124 | (call_indirect $over-i32 (i32.const 14) 125 | (i32.sub (get_local 0) (i32.const 1)) 126 | ) 127 | ) 128 | ) 129 | 130 | ;; Stack exhaustion 131 | 132 | ;; Implementations are required to have every call consume some abstract 133 | ;; resource towards exhausting some abstract finite limit, such that 134 | ;; infinitely recursive test cases reliably trap in finite time. This is 135 | ;; because otherwise applications could come to depend on it on those 136 | ;; implementations and be incompatible with implementations that don't do 137 | ;; it (or don't do it under the same circumstances). 138 | 139 | (func "runaway" $runaway (call_indirect $proc (i32.const 16))) 140 | 141 | (func "mutual-runaway" $mutual-runaway1 (call_indirect $proc (i32.const 18))) 142 | (func $mutual-runaway2 (call_indirect $proc (i32.const 17))) 143 | ) 144 | 145 | (assert_return (invoke "type-i32") (i32.const 0x132)) 146 | (assert_return (invoke "type-i64") (i64.const 0x164)) 147 | (assert_return (invoke "type-f32") (f32.const 0xf32)) 148 | (assert_return (invoke "type-f64") (f64.const 0xf64)) 149 | 150 | (assert_return (invoke "type-index") (i64.const 100)) 151 | 152 | (assert_return (invoke "type-first-i32") (i32.const 32)) 153 | (assert_return (invoke "type-first-i64") (i64.const 64)) 154 | (assert_return (invoke "type-first-f32") (f32.const 1.32)) 155 | (assert_return (invoke "type-first-f64") (f64.const 1.64)) 156 | 157 | (assert_return (invoke "type-second-i32") (i32.const 32)) 158 | (assert_return (invoke "type-second-i64") (i64.const 64)) 159 | (assert_return (invoke "type-second-f32") (f32.const 32)) 160 | (assert_return (invoke "type-second-f64") (f64.const 64.1)) 161 | 162 | (assert_return (invoke "dispatch" (i32.const 5) (i64.const 2)) (i64.const 2)) 163 | (assert_return (invoke "dispatch" (i32.const 5) (i64.const 5)) (i64.const 5)) 164 | (assert_return (invoke "dispatch" (i32.const 12) (i64.const 5)) (i64.const 120)) 165 | (assert_return (invoke "dispatch" (i32.const 13) (i64.const 5)) (i64.const 8)) 166 | (assert_trap (invoke "dispatch" (i32.const 0) (i64.const 2)) "indirect call signature mismatch") 167 | (assert_trap (invoke "dispatch" (i32.const 15) (i64.const 2)) "indirect call signature mismatch") 168 | (assert_trap (invoke "dispatch" (i32.const 20) (i64.const 2)) "undefined table index") 169 | (assert_trap (invoke "dispatch" (i32.const -1) (i64.const 2)) "undefined table index") 170 | (assert_trap (invoke "dispatch" (i32.const 1213432423) (i64.const 2)) "undefined table index") 171 | 172 | (assert_return (invoke "fac" (i64.const 0)) (i64.const 1)) 173 | (assert_return (invoke "fac" (i64.const 1)) (i64.const 1)) 174 | (assert_return (invoke "fac" (i64.const 5)) (i64.const 120)) 175 | (assert_return (invoke "fac" (i64.const 25)) (i64.const 7034535277573963776)) 176 | 177 | (assert_return (invoke "fib" (i64.const 0)) (i64.const 1)) 178 | (assert_return (invoke "fib" (i64.const 1)) (i64.const 1)) 179 | (assert_return (invoke "fib" (i64.const 2)) (i64.const 2)) 180 | (assert_return (invoke "fib" (i64.const 5)) (i64.const 8)) 181 | (assert_return (invoke "fib" (i64.const 20)) (i64.const 10946)) 182 | 183 | (assert_return (invoke "even" (i32.const 0)) (i32.const 44)) 184 | (assert_return (invoke "even" (i32.const 1)) (i32.const 99)) 185 | (assert_return (invoke "even" (i32.const 100)) (i32.const 44)) 186 | (assert_return (invoke "even" (i32.const 77)) (i32.const 99)) 187 | (assert_return (invoke "odd" (i32.const 0)) (i32.const 99)) 188 | (assert_return (invoke "odd" (i32.const 1)) (i32.const 44)) 189 | (assert_return (invoke "odd" (i32.const 200)) (i32.const 99)) 190 | (assert_return (invoke "odd" (i32.const 77)) (i32.const 44)) 191 | 192 | (assert_trap (invoke "runaway") "call stack exhausted") 193 | (assert_trap (invoke "mutual-runaway") "call stack exhausted") 194 | 195 | 196 | ;; Invalid typing 197 | 198 | (assert_invalid 199 | (module 200 | (type (func)) 201 | (func $type-void-vs-num (i32.eqz (call_indirect 0 (i32.const 0)))) 202 | ) 203 | "type mismatch" 204 | ) 205 | (assert_invalid 206 | (module 207 | (type (func (result i64))) 208 | (func $type-num-vs-num (i32.eqz (call_indirect 0 (i32.const 0)))) 209 | ) 210 | "type mismatch" 211 | ) 212 | 213 | (assert_invalid 214 | (module 215 | (type (func (param i32))) 216 | (func $arity-0-vs-1 (call_indirect 0 (i32.const 0))) 217 | ) 218 | "arity mismatch" 219 | ) 220 | (assert_invalid 221 | (module 222 | (type (func (param f64 i32))) 223 | (func $arity-0-vs-2 (call_indirect 0 (i32.const 0))) 224 | ) 225 | "arity mismatch" 226 | ) 227 | (assert_invalid 228 | (module 229 | (type (func)) 230 | (func $arity-1-vs-0 (call_indirect 0 (i32.const 0) (i32.const 1))) 231 | ) 232 | "arity mismatch" 233 | ) 234 | (assert_invalid 235 | (module 236 | (type (func)) 237 | (func $arity-2-vs-0 238 | (call_indirect 0 (i32.const 0) (f64.const 2) (i32.const 1)) 239 | ) 240 | ) 241 | "arity mismatch" 242 | ) 243 | 244 | (assert_invalid 245 | (module 246 | (type (func (param i32 i32))) 247 | (func $arity-nop-first 248 | (call_indirect 0 (i32.const 0) (nop) (i32.const 1) (i32.const 2)) 249 | ) 250 | ) 251 | "arity mismatch" 252 | ) 253 | (assert_invalid 254 | (module 255 | (type (func (param i32 i32))) 256 | (func $arity-nop-mid 257 | (call_indirect 0 (i32.const 0) (i32.const 1) (nop) (i32.const 2)) 258 | ) 259 | ) 260 | "arity mismatch" 261 | ) 262 | (assert_invalid 263 | (module 264 | (type (func (param i32 i32))) 265 | (func $arity-nop-last 266 | (call_indirect 0 (i32.const 0) (i32.const 1) (i32.const 2) (nop)) 267 | ) 268 | ) 269 | "arity mismatch" 270 | ) 271 | 272 | (assert_invalid 273 | (module 274 | (type (func (param i32))) 275 | (func $type-func-void-vs-i32 (call_indirect 0 (nop) (i32.const 1))) 276 | ) 277 | "type mismatch" 278 | ) 279 | (assert_invalid 280 | (module 281 | (type (func (param i32))) 282 | (func $type-func-num-vs-i32 (call_indirect 0 (i64.const 1) (i32.const 0))) 283 | ) 284 | "type mismatch" 285 | ) 286 | 287 | (assert_invalid 288 | (module 289 | (type (func (param i32 i32))) 290 | (func $type-first-void-vs-num 291 | (call_indirect 0 (i32.const 0) (nop) (i32.const 1)) 292 | ) 293 | ) 294 | "type mismatch" 295 | ) 296 | (assert_invalid 297 | (module 298 | (type (func (param i32 i32))) 299 | (func $type-second-void-vs-num 300 | (call_indirect 0 (i32.const 0) (i32.const 1) (nop)) 301 | ) 302 | ) 303 | "type mismatch" 304 | ) 305 | (assert_invalid 306 | (module 307 | (type (func (param i32 f64))) 308 | (func $type-first-num-vs-num 309 | (call_indirect 0 (i32.const 0) (f64.const 1) (i32.const 1)) 310 | ) 311 | ) 312 | "type mismatch" 313 | ) 314 | (assert_invalid 315 | (module 316 | (type (func (param f64 i32))) 317 | (func $type-second-num-vs-num 318 | (call_indirect 0 (i32.const 0) (i32.const 1) (f64.const 1)) 319 | ) 320 | ) 321 | "type mismatch" 322 | ) 323 | 324 | 325 | ;; Unbound type 326 | 327 | (assert_invalid 328 | (module (func $unbound-type (call_indirect 1 (i32.const 0)))) 329 | "unknown function type" 330 | ) 331 | (assert_invalid 332 | (module (func $large-type (call_indirect 10001232130000 (i32.const 0)))) 333 | "unknown function type" 334 | ) 335 | -------------------------------------------------------------------------------- /test/endianness.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (memory 1) 3 | 4 | ;; Stores an i16 value in little-endian-format 5 | (func $i16_store_little (param $address i32) (param $value i32) 6 | (i32.store8 (get_local $address) (get_local $value)) 7 | (i32.store8 (i32.add (get_local $address) (i32.const 1)) (i32.shr_u (get_local $value) (i32.const 8))) 8 | ) 9 | 10 | ;; Stores an i32 value in little-endian format 11 | (func $i32_store_little (param $address i32) (param $value i32) 12 | (call $i16_store_little (get_local $address) (get_local $value)) 13 | (call $i16_store_little (i32.add (get_local $address) (i32.const 2)) (i32.shr_u (get_local $value) (i32.const 16))) 14 | ) 15 | 16 | ;; Stores an i64 value in little-endian format 17 | (func $i64_store_little (param $address i32) (param $value i64) 18 | (call $i32_store_little (get_local $address) (i32.wrap/i64 (get_local $value))) 19 | (call $i32_store_little (i32.add (get_local $address) (i32.const 4)) (i32.wrap/i64 (i64.shr_u (get_local $value) (i64.const 32)))) 20 | ) 21 | 22 | ;; Loads an i16 value in little-endian format 23 | (func $i16_load_little (param $address i32) (result i32) 24 | (i32.or 25 | (i32.load8_u (get_local $address)) 26 | (i32.shl (i32.load8_u (i32.add (get_local $address) (i32.const 1))) (i32.const 8)) 27 | ) 28 | ) 29 | 30 | ;; Loads an i32 value in little-endian format 31 | (func $i32_load_little (param $address i32) (result i32) 32 | (i32.or 33 | (call $i16_load_little (get_local $address)) 34 | (i32.shl (call $i16_load_little (i32.add (get_local $address) (i32.const 2))) (i32.const 16)) 35 | ) 36 | ) 37 | 38 | ;; Loads an i64 value in little-endian format 39 | (func $i64_load_little (param $address i32) (result i64) 40 | (i64.or 41 | (i64.extend_u/i32 (call $i32_load_little (get_local $address))) 42 | (i64.shl (i64.extend_u/i32 (call $i32_load_little (i32.add (get_local $address) (i32.const 4)))) (i64.const 32)) 43 | ) 44 | ) 45 | 46 | (func $i32_load16_s (param $value i32) (result i32) 47 | (call $i16_store_little (i32.const 0) (get_local $value)) 48 | (i32.load16_s (i32.const 0)) 49 | ) 50 | 51 | (func $i32_load16_u (param $value i32) (result i32) 52 | (call $i16_store_little (i32.const 0) (get_local $value)) 53 | (i32.load16_u (i32.const 0)) 54 | ) 55 | 56 | (func $i32_load (param $value i32) (result i32) 57 | (call $i32_store_little (i32.const 0) (get_local $value)) 58 | (i32.load (i32.const 0)) 59 | ) 60 | 61 | (func $i64_load16_s (param $value i64) (result i64) 62 | (call $i16_store_little (i32.const 0) (i32.wrap/i64 (get_local $value))) 63 | (i64.load16_s (i32.const 0)) 64 | ) 65 | 66 | (func $i64_load16_u (param $value i64) (result i64) 67 | (call $i16_store_little (i32.const 0) (i32.wrap/i64 (get_local $value))) 68 | (i64.load16_u (i32.const 0)) 69 | ) 70 | 71 | (func $i64_load32_s (param $value i64) (result i64) 72 | (call $i32_store_little (i32.const 0) (i32.wrap/i64 (get_local $value))) 73 | (i64.load32_s (i32.const 0)) 74 | ) 75 | 76 | (func $i64_load32_u (param $value i64) (result i64) 77 | (call $i32_store_little (i32.const 0) (i32.wrap/i64 (get_local $value))) 78 | (i64.load32_u (i32.const 0)) 79 | ) 80 | 81 | (func $i64_load (param $value i64) (result i64) 82 | (call $i64_store_little (i32.const 0) (get_local $value)) 83 | (i64.load (i32.const 0)) 84 | ) 85 | 86 | (func $f32_load (param $value f32) (result f32) 87 | (call $i32_store_little (i32.const 0) (i32.reinterpret/f32 (get_local $value))) 88 | (f32.load (i32.const 0)) 89 | ) 90 | 91 | (func $f64_load (param $value f64) (result f64) 92 | (call $i64_store_little (i32.const 0) (i64.reinterpret/f64 (get_local $value))) 93 | (f64.load (i32.const 0)) 94 | ) 95 | 96 | 97 | (func $i32_store16 (param $value i32) (result i32) 98 | (i32.store16 (i32.const 0) (get_local $value)) 99 | (call $i16_load_little (i32.const 0)) 100 | ) 101 | 102 | (func $i32_store (param $value i32) (result i32) 103 | (i32.store (i32.const 0) (get_local $value)) 104 | (call $i32_load_little (i32.const 0)) 105 | ) 106 | 107 | (func $i64_store16 (param $value i64) (result i64) 108 | (i64.store16 (i32.const 0) (get_local $value)) 109 | (i64.extend_u/i32 (call $i16_load_little (i32.const 0))) 110 | ) 111 | 112 | (func $i64_store32 (param $value i64) (result i64) 113 | (i64.store32 (i32.const 0) (get_local $value)) 114 | (i64.extend_u/i32 (call $i32_load_little (i32.const 0))) 115 | ) 116 | 117 | (func $i64_store (param $value i64) (result i64) 118 | (i64.store (i32.const 0) (get_local $value)) 119 | (call $i64_load_little (i32.const 0)) 120 | ) 121 | 122 | (func $f32_store (param $value f32) (result f32) 123 | (f32.store (i32.const 0) (get_local $value)) 124 | (f32.reinterpret/i32 (call $i32_load_little (i32.const 0))) 125 | ) 126 | 127 | (func $f64_store (param $value f64) (result f64) 128 | (f64.store (i32.const 0) (get_local $value)) 129 | (f64.reinterpret/i64 (call $i64_load_little (i32.const 0))) 130 | ) 131 | 132 | (export "i32_load16_s" $i32_load16_s) 133 | (export "i32_load16_u" $i32_load16_u) 134 | (export "i32_load" $i32_load) 135 | 136 | (export "i64_load16_s" $i64_load16_s) 137 | (export "i64_load16_u" $i64_load16_u) 138 | (export "i64_load32_s" $i64_load32_s) 139 | (export "i64_load32_u" $i64_load32_u) 140 | (export "i64_load" $i64_load) 141 | 142 | (export "f32_load" $f32_load) 143 | (export "f64_load" $f64_load) 144 | 145 | 146 | (export "i32_store16" $i32_store16) 147 | (export "i32_store" $i32_store) 148 | 149 | (export "i64_store16" $i64_store16) 150 | (export "i64_store32" $i64_store32) 151 | (export "i64_store" $i64_store) 152 | 153 | (export "f32_store" $f32_store) 154 | (export "f64_store" $f64_store) 155 | ) 156 | 157 | (assert_return (invoke "i32_load16_s" (i32.const -1)) (i32.const -1)) 158 | (assert_return (invoke "i32_load16_s" (i32.const -4242)) (i32.const -4242)) 159 | (assert_return (invoke "i32_load16_s" (i32.const 42)) (i32.const 42)) 160 | (assert_return (invoke "i32_load16_s" (i32.const 0x3210)) (i32.const 0x3210)) 161 | 162 | (assert_return (invoke "i32_load16_u" (i32.const -1)) (i32.const 0xFFFF)) 163 | (assert_return (invoke "i32_load16_u" (i32.const -4242)) (i32.const 61294)) 164 | (assert_return (invoke "i32_load16_u" (i32.const 42)) (i32.const 42)) 165 | (assert_return (invoke "i32_load16_u" (i32.const 0xCAFE)) (i32.const 0xCAFE)) 166 | 167 | (assert_return (invoke "i32_load" (i32.const -1)) (i32.const -1)) 168 | (assert_return (invoke "i32_load" (i32.const -42424242)) (i32.const -42424242)) 169 | (assert_return (invoke "i32_load" (i32.const 42424242)) (i32.const 42424242)) 170 | (assert_return (invoke "i32_load" (i32.const 0xABAD1DEA)) (i32.const 0xABAD1DEA)) 171 | 172 | (assert_return (invoke "i64_load16_s" (i64.const -1)) (i64.const -1)) 173 | (assert_return (invoke "i64_load16_s" (i64.const -4242)) (i64.const -4242)) 174 | (assert_return (invoke "i64_load16_s" (i64.const 42)) (i64.const 42)) 175 | (assert_return (invoke "i64_load16_s" (i64.const 0x3210)) (i64.const 0x3210)) 176 | 177 | (assert_return (invoke "i64_load16_u" (i64.const -1)) (i64.const 0xFFFF)) 178 | (assert_return (invoke "i64_load16_u" (i64.const -4242)) (i64.const 61294)) 179 | (assert_return (invoke "i64_load16_u" (i64.const 42)) (i64.const 42)) 180 | (assert_return (invoke "i64_load16_u" (i64.const 0xCAFE)) (i64.const 0xCAFE)) 181 | 182 | (assert_return (invoke "i64_load32_s" (i64.const -1)) (i64.const -1)) 183 | (assert_return (invoke "i64_load32_s" (i64.const -42424242)) (i64.const -42424242)) 184 | (assert_return (invoke "i64_load32_s" (i64.const 42424242)) (i64.const 42424242)) 185 | (assert_return (invoke "i64_load32_s" (i64.const 0x12345678)) (i64.const 0x12345678)) 186 | 187 | (assert_return (invoke "i64_load32_u" (i64.const -1)) (i64.const 0xFFFFFFFF)) 188 | (assert_return (invoke "i64_load32_u" (i64.const -42424242)) (i64.const 4252543054)) 189 | (assert_return (invoke "i64_load32_u" (i64.const 42424242)) (i64.const 42424242)) 190 | (assert_return (invoke "i64_load32_u" (i64.const 0xABAD1DEA)) (i64.const 0xABAD1DEA)) 191 | 192 | (assert_return (invoke "i64_load" (i64.const -1)) (i64.const -1)) 193 | (assert_return (invoke "i64_load" (i64.const -42424242)) (i64.const -42424242)) 194 | (assert_return (invoke "i64_load" (i64.const 0xABAD1DEA)) (i64.const 0xABAD1DEA)) 195 | (assert_return (invoke "i64_load" (i64.const 0xABADCAFEDEAD1DEA)) (i64.const 0xABADCAFEDEAD1DEA)) 196 | 197 | (assert_return (invoke "f32_load" (f32.const -1)) (f32.const -1)) 198 | (assert_return (invoke "f32_load" (f32.const 1234e-5)) (f32.const 1234e-5)) 199 | (assert_return (invoke "f32_load" (f32.const 4242.4242)) (f32.const 4242.4242)) 200 | (assert_return (invoke "f32_load" (f32.const 0x1.fffffep+127)) (f32.const 0x1.fffffep+127)) 201 | 202 | (assert_return (invoke "f64_load" (f64.const -1)) (f64.const -1)) 203 | (assert_return (invoke "f64_load" (f64.const 123456789e-5)) (f64.const 123456789e-5)) 204 | (assert_return (invoke "f64_load" (f64.const 424242.424242)) (f64.const 424242.424242)) 205 | (assert_return (invoke "f64_load" (f64.const 0x1.fffffffffffffp+1023)) (f64.const 0x1.fffffffffffffp+1023)) 206 | 207 | 208 | (assert_return (invoke "i32_store16" (i32.const -1)) (i32.const 0xFFFF)) 209 | (assert_return (invoke "i32_store16" (i32.const -4242)) (i32.const 61294)) 210 | (assert_return (invoke "i32_store16" (i32.const 42)) (i32.const 42)) 211 | (assert_return (invoke "i32_store16" (i32.const 0xCAFE)) (i32.const 0xCAFE)) 212 | 213 | (assert_return (invoke "i32_store" (i32.const -1)) (i32.const -1)) 214 | (assert_return (invoke "i32_store" (i32.const -4242)) (i32.const -4242)) 215 | (assert_return (invoke "i32_store" (i32.const 42424242)) (i32.const 42424242)) 216 | (assert_return (invoke "i32_store" (i32.const 0xDEADCAFE)) (i32.const 0xDEADCAFE)) 217 | 218 | (assert_return (invoke "i64_store16" (i64.const -1)) (i64.const 0xFFFF)) 219 | (assert_return (invoke "i64_store16" (i64.const -4242)) (i64.const 61294)) 220 | (assert_return (invoke "i64_store16" (i64.const 42)) (i64.const 42)) 221 | (assert_return (invoke "i64_store16" (i64.const 0xCAFE)) (i64.const 0xCAFE)) 222 | 223 | (assert_return (invoke "i64_store32" (i64.const -1)) (i64.const 0xFFFFFFFF)) 224 | (assert_return (invoke "i64_store32" (i64.const -4242)) (i64.const 4294963054)) 225 | (assert_return (invoke "i64_store32" (i64.const 42424242)) (i64.const 42424242)) 226 | (assert_return (invoke "i64_store32" (i64.const 0xDEADCAFE)) (i64.const 0xDEADCAFE)) 227 | 228 | (assert_return (invoke "i64_store" (i64.const -1)) (i64.const -1)) 229 | (assert_return (invoke "i64_store" (i64.const -42424242)) (i64.const -42424242)) 230 | (assert_return (invoke "i64_store" (i64.const 0xABAD1DEA)) (i64.const 0xABAD1DEA)) 231 | (assert_return (invoke "i64_store" (i64.const 0xABADCAFEDEAD1DEA)) (i64.const 0xABADCAFEDEAD1DEA)) 232 | 233 | (assert_return (invoke "f32_store" (f32.const -1)) (f32.const -1)) 234 | (assert_return (invoke "f32_store" (f32.const 1234e-5)) (f32.const 1234e-5)) 235 | (assert_return (invoke "f32_store" (f32.const 4242.4242)) (f32.const 4242.4242)) 236 | (assert_return (invoke "f32_store" (f32.const 0x1.fffffep+127)) (f32.const 0x1.fffffep+127)) 237 | 238 | (assert_return (invoke "f64_store" (f64.const -1)) (f64.const -1)) 239 | (assert_return (invoke "f64_store" (f64.const 123456789e-5)) (f64.const 123456789e-5)) 240 | (assert_return (invoke "f64_store" (f64.const 424242.424242)) (f64.const 424242.424242)) 241 | (assert_return (invoke "f64_store" (f64.const 0x1.fffffffffffffp+1023)) (f64.const 0x1.fffffffffffffp+1023)) 242 | -------------------------------------------------------------------------------- /test/exports.wast: -------------------------------------------------------------------------------- 1 | (module (func (i32.const 1)) (export "a" 0)) 2 | (module (func (i32.const 1)) (export "a" 0) (export "b" 0)) 3 | (module (func (i32.const 1)) (func (i32.const 2)) (export "a" 0) (export "b" 1)) 4 | (assert_invalid 5 | (module (func (i32.const 1)) (export "a" 1)) 6 | "unknown function 1") 7 | (assert_invalid 8 | (module (func (i32.const 1)) (func (i32.const 2)) (export "a" 0) (export "a" 1)) 9 | "duplicate export name") 10 | (assert_invalid 11 | (module (func (i32.const 1)) (export "a" 0) (export "a" 0)) 12 | "duplicate export name") 13 | 14 | (module 15 | (func $f (param $n i32) (result i32) 16 | (return (i32.add (get_local $n) (i32.const 1))) 17 | ) 18 | 19 | (export "e" $f) 20 | ) 21 | 22 | (assert_return (invoke "e" (i32.const 42)) (i32.const 43)) 23 | 24 | (module (memory 0 0) (export "a" memory)) 25 | (module (memory 0 0) (export "a" memory) (export "b" memory)) 26 | (assert_invalid (module (export "a" memory)) "no memory to export") 27 | -------------------------------------------------------------------------------- /test/fac.wast: -------------------------------------------------------------------------------- 1 | (module 2 | ;; Recursive factorial 3 | (func (param i64) (result i64) 4 | (if (i64.eq (get_local 0) (i64.const 0)) 5 | (i64.const 1) 6 | (i64.mul (get_local 0) (call 0 (i64.sub (get_local 0) (i64.const 1)))) 7 | ) 8 | ) 9 | 10 | ;; Recursive factorial named 11 | (func $fac-rec (param $n i64) (result i64) 12 | (if (i64.eq (get_local $n) (i64.const 0)) 13 | (i64.const 1) 14 | (i64.mul 15 | (get_local $n) 16 | (call $fac-rec (i64.sub (get_local $n) (i64.const 1))) 17 | ) 18 | ) 19 | ) 20 | 21 | ;; Iterative factorial 22 | (func (param i64) (result i64) 23 | (local i64 i64) 24 | (set_local 1 (get_local 0)) 25 | (set_local 2 (i64.const 1)) 26 | (loop 27 | (if 28 | (i64.eq (get_local 1) (i64.const 0)) 29 | (br 2) 30 | (block 31 | (set_local 2 (i64.mul (get_local 1) (get_local 2))) 32 | (set_local 1 (i64.sub (get_local 1) (i64.const 1))) 33 | ) 34 | ) 35 | (br 0) 36 | ) 37 | (get_local 2) 38 | ) 39 | 40 | ;; Iterative factorial named 41 | (func $fac-iter (param $n i64) (result i64) 42 | (local $i i64) 43 | (local $res i64) 44 | (set_local $i (get_local $n)) 45 | (set_local $res (i64.const 1)) 46 | (loop $done $loop 47 | (if 48 | (i64.eq (get_local $i) (i64.const 0)) 49 | (br $done) 50 | (block 51 | (set_local $res (i64.mul (get_local $i) (get_local $res))) 52 | (set_local $i (i64.sub (get_local $i) (i64.const 1))) 53 | ) 54 | ) 55 | (br $loop) 56 | ) 57 | (get_local $res) 58 | ) 59 | 60 | ;; More-realistically optimized factorial. 61 | (func $fac-opt (param i64) (result i64) 62 | (local i64) 63 | (set_local 1 (i64.const 1)) 64 | (block 65 | (br_if 0 (i64.lt_s (get_local 0) (i64.const 2))) 66 | (loop 67 | (set_local 1 (i64.mul (get_local 1) (get_local 0))) 68 | (set_local 0 (i64.add (get_local 0) (i64.const -1))) 69 | (br_if 0 (i64.gt_s (get_local 0) (i64.const 1))) 70 | ) 71 | ) 72 | (get_local 1) 73 | ) 74 | 75 | (export "fac-rec" 0) 76 | (export "fac-iter" 2) 77 | (export "fac-rec-named" $fac-rec) 78 | (export "fac-iter-named" $fac-iter) 79 | (export "fac-opt" $fac-opt) 80 | ) 81 | 82 | (assert_return (invoke "fac-rec" (i64.const 25)) (i64.const 7034535277573963776)) 83 | (assert_return (invoke "fac-iter" (i64.const 25)) (i64.const 7034535277573963776)) 84 | (assert_return (invoke "fac-rec-named" (i64.const 25)) (i64.const 7034535277573963776)) 85 | (assert_return (invoke "fac-iter-named" (i64.const 25)) (i64.const 7034535277573963776)) 86 | (assert_return (invoke "fac-opt" (i64.const 25)) (i64.const 7034535277573963776)) 87 | (assert_trap (invoke "fac-rec" (i64.const 1073741824)) "call stack exhausted") 88 | -------------------------------------------------------------------------------- /test/float_literals.wast: -------------------------------------------------------------------------------- 1 | ;; Test floating-point literal parsing. 2 | 3 | (module 4 | ;; f32 special values 5 | (func $f32.nan (result i32) (i32.reinterpret/f32 (f32.const nan))) 6 | (func $f32.positive_nan (result i32) (i32.reinterpret/f32 (f32.const +nan))) 7 | (func $f32.negative_nan (result i32) (i32.reinterpret/f32 (f32.const -nan))) 8 | (func $f32.plain_nan (result i32) (i32.reinterpret/f32 (f32.const nan:0x400000))) 9 | (func $f32.informally_known_as_plain_snan (result i32) (i32.reinterpret/f32 (f32.const nan:0x200000))) 10 | (func $f32.allones_nan (result i32) (i32.reinterpret/f32 (f32.const -nan:0x7fffff))) 11 | (func $f32.misc_nan (result i32) (i32.reinterpret/f32 (f32.const nan:0x012345))) 12 | (func $f32.misc_positive_nan (result i32) (i32.reinterpret/f32 (f32.const +nan:0x304050))) 13 | (func $f32.misc_negative_nan (result i32) (i32.reinterpret/f32 (f32.const -nan:0x2abcde))) 14 | (func $f32.infinity (result i32) (i32.reinterpret/f32 (f32.const infinity))) 15 | (func $f32.positive_infinity (result i32) (i32.reinterpret/f32 (f32.const +infinity))) 16 | (func $f32.negative_infinity (result i32) (i32.reinterpret/f32 (f32.const -infinity))) 17 | 18 | ;; f32 numbers 19 | (func $f32.zero (result i32) (i32.reinterpret/f32 (f32.const 0x0.0p0))) 20 | (func $f32.positive_zero (result i32) (i32.reinterpret/f32 (f32.const +0x0.0p0))) 21 | (func $f32.negative_zero (result i32) (i32.reinterpret/f32 (f32.const -0x0.0p0))) 22 | (func $f32.misc (result i32) (i32.reinterpret/f32 (f32.const 0x1.921fb6p+2))) 23 | (func $f32.min_positive (result i32) (i32.reinterpret/f32 (f32.const 0x1p-149))) 24 | (func $f32.min_normal (result i32) (i32.reinterpret/f32 (f32.const 0x1p-126))) 25 | (func $f32.max_finite (result i32) (i32.reinterpret/f32 (f32.const 0x1.fffffep+127))) 26 | (func $f32.max_subnormal (result i32) (i32.reinterpret/f32 (f32.const 0x1.fffffcp-127))) 27 | (func $f32.trailing_dot (result i32) (i32.reinterpret/f32 (f32.const 0x1.p10))) 28 | 29 | ;; f32 in decimal format 30 | (func $f32_dec.zero (result i32) (i32.reinterpret/f32 (f32.const 0.0e0))) 31 | (func $f32_dec.positive_zero (result i32) (i32.reinterpret/f32 (f32.const +0.0e0))) 32 | (func $f32_dec.negative_zero (result i32) (i32.reinterpret/f32 (f32.const -0.0e0))) 33 | (func $f32_dec.misc (result i32) (i32.reinterpret/f32 (f32.const 6.28318548202514648))) 34 | (func $f32_dec.min_positive (result i32) (i32.reinterpret/f32 (f32.const 1.4013e-45))) 35 | (func $f32_dec.min_normal (result i32) (i32.reinterpret/f32 (f32.const 1.1754944e-38))) 36 | (func $f32_dec.max_subnormal (result i32) (i32.reinterpret/f32 (f32.const 1.1754942e-38))) 37 | (func $f32_dec.max_finite (result i32) (i32.reinterpret/f32 (f32.const 3.4028234e+38))) 38 | (func $f32_dec.trailing_dot (result i32) (i32.reinterpret/f32 (f32.const 1.e10))) 39 | 40 | ;; f64 special values 41 | (func $f64.nan (result i64) (i64.reinterpret/f64 (f64.const nan))) 42 | (func $f64.positive_nan (result i64) (i64.reinterpret/f64 (f64.const +nan))) 43 | (func $f64.negative_nan (result i64) (i64.reinterpret/f64 (f64.const -nan))) 44 | (func $f64.plain_nan (result i64) (i64.reinterpret/f64 (f64.const nan:0x8000000000000))) 45 | (func $f64.informally_known_as_plain_snan (result i64) (i64.reinterpret/f64 (f64.const nan:0x4000000000000))) 46 | (func $f64.allones_nan (result i64) (i64.reinterpret/f64 (f64.const -nan:0xfffffffffffff))) 47 | (func $f64.misc_nan (result i64) (i64.reinterpret/f64 (f64.const nan:0x0123456789abc))) 48 | (func $f64.misc_positive_nan (result i64) (i64.reinterpret/f64 (f64.const +nan:0x3040506070809))) 49 | (func $f64.misc_negative_nan (result i64) (i64.reinterpret/f64 (f64.const -nan:0x2abcdef012345))) 50 | (func $f64.infinity (result i64) (i64.reinterpret/f64 (f64.const infinity))) 51 | (func $f64.positive_infinity (result i64) (i64.reinterpret/f64 (f64.const +infinity))) 52 | (func $f64.negative_infinity (result i64) (i64.reinterpret/f64 (f64.const -infinity))) 53 | 54 | ;; f64 numbers 55 | (func $f64.zero (result i64) (i64.reinterpret/f64 (f64.const 0x0.0p0))) 56 | (func $f64.positive_zero (result i64) (i64.reinterpret/f64 (f64.const +0x0.0p0))) 57 | (func $f64.negative_zero (result i64) (i64.reinterpret/f64 (f64.const -0x0.0p0))) 58 | (func $f64.misc (result i64) (i64.reinterpret/f64 (f64.const 0x1.921fb54442d18p+2))) 59 | (func $f64.min_positive (result i64) (i64.reinterpret/f64 (f64.const 0x0.0000000000001p-1022))) 60 | (func $f64.min_normal (result i64) (i64.reinterpret/f64 (f64.const 0x1p-1022))) 61 | (func $f64.max_subnormal (result i64) (i64.reinterpret/f64 (f64.const 0x0.fffffffffffffp-1022))) 62 | (func $f64.max_finite (result i64) (i64.reinterpret/f64 (f64.const 0x1.fffffffffffffp+1023))) 63 | (func $f64.trailing_dot (result i64) (i64.reinterpret/f64 (f64.const 0x1.p100))) 64 | 65 | ;; f64 numbers in decimal format 66 | (func $f64_dec.zero (result i64) (i64.reinterpret/f64 (f64.const 0.0e0))) 67 | (func $f64_dec.positive_zero (result i64) (i64.reinterpret/f64 (f64.const +0.0e0))) 68 | (func $f64_dec.negative_zero (result i64) (i64.reinterpret/f64 (f64.const -0.0e0))) 69 | (func $f64_dec.misc (result i64) (i64.reinterpret/f64 (f64.const 6.28318530717958623))) 70 | (func $f64_dec.min_positive (result i64) (i64.reinterpret/f64 (f64.const 4.94066e-324))) 71 | (func $f64_dec.min_normal (result i64) (i64.reinterpret/f64 (f64.const 2.2250738585072012e-308))) 72 | (func $f64_dec.max_subnormal (result i64) (i64.reinterpret/f64 (f64.const 2.2250738585072011e-308))) 73 | (func $f64_dec.max_finite (result i64) (i64.reinterpret/f64 (f64.const 1.7976931348623157e+308))) 74 | (func $f64_dec.trailing_dot (result i64) (i64.reinterpret/f64 (f64.const 1.e100))) 75 | 76 | (export "f32.nan" $f32.nan) 77 | (export "f32.positive_nan" $f32.positive_nan) 78 | (export "f32.negative_nan" $f32.negative_nan) 79 | (export "f32.plain_nan" $f32.plain_nan) 80 | (export "f32.informally_known_as_plain_snan" $f32.informally_known_as_plain_snan) 81 | (export "f32.allones_nan" $f32.allones_nan) 82 | (export "f32.misc_nan" $f32.misc_nan) 83 | (export "f32.misc_positive_nan" $f32.misc_positive_nan) 84 | (export "f32.misc_negative_nan" $f32.misc_negative_nan) 85 | (export "f32.infinity" $f32.infinity) 86 | (export "f32.positive_infinity" $f32.positive_infinity) 87 | (export "f32.negative_infinity" $f32.negative_infinity) 88 | (export "f32.zero" $f32.zero) 89 | (export "f32.positive_zero" $f32.positive_zero) 90 | (export "f32.negative_zero" $f32.negative_zero) 91 | (export "f32.misc" $f32.misc) 92 | (export "f32.min_positive" $f32.min_positive) 93 | (export "f32.min_normal" $f32.min_normal) 94 | (export "f32.max_subnormal" $f32.max_subnormal) 95 | (export "f32.max_finite" $f32.max_finite) 96 | (export "f32.trailing_dot" $f32.trailing_dot) 97 | (export "f32_dec.zero" $f32_dec.zero) 98 | (export "f32_dec.positive_zero" $f32_dec.positive_zero) 99 | (export "f32_dec.negative_zero" $f32_dec.negative_zero) 100 | (export "f32_dec.misc" $f32_dec.misc) 101 | (export "f32_dec.min_positive" $f32_dec.min_positive) 102 | (export "f32_dec.min_normal" $f32_dec.min_normal) 103 | (export "f32_dec.max_subnormal" $f32_dec.max_subnormal) 104 | (export "f32_dec.max_finite" $f32_dec.max_finite) 105 | (export "f32_dec.trailing_dot" $f32_dec.trailing_dot) 106 | 107 | (export "f64.nan" $f64.nan) 108 | (export "f64.positive_nan" $f64.positive_nan) 109 | (export "f64.negative_nan" $f64.negative_nan) 110 | (export "f64.plain_nan" $f64.plain_nan) 111 | (export "f64.informally_known_as_plain_snan" $f64.informally_known_as_plain_snan) 112 | (export "f64.allones_nan" $f64.allones_nan) 113 | (export "f64.misc_nan" $f64.misc_nan) 114 | (export "f64.misc_positive_nan" $f64.misc_positive_nan) 115 | (export "f64.misc_negative_nan" $f64.misc_negative_nan) 116 | (export "f64.infinity" $f64.infinity) 117 | (export "f64.positive_infinity" $f64.positive_infinity) 118 | (export "f64.negative_infinity" $f64.negative_infinity) 119 | (export "f64.zero" $f64.zero) 120 | (export "f64.positive_zero" $f64.positive_zero) 121 | (export "f64.negative_zero" $f64.negative_zero) 122 | (export "f64.misc" $f64.misc) 123 | (export "f64.min_positive" $f64.min_positive) 124 | (export "f64.min_normal" $f64.min_normal) 125 | (export "f64.max_subnormal" $f64.max_subnormal) 126 | (export "f64.max_finite" $f64.max_finite) 127 | (export "f64.trailing_dot" $f64.trailing_dot) 128 | (export "f64_dec.zero" $f64_dec.zero) 129 | (export "f64_dec.positive_zero" $f64_dec.positive_zero) 130 | (export "f64_dec.negative_zero" $f64_dec.negative_zero) 131 | (export "f64_dec.misc" $f64_dec.misc) 132 | (export "f64_dec.min_positive" $f64_dec.min_positive) 133 | (export "f64_dec.min_normal" $f64_dec.min_normal) 134 | (export "f64_dec.max_subnormal" $f64_dec.max_subnormal) 135 | (export "f64_dec.max_finite" $f64_dec.max_finite) 136 | (export "f64_dec.trailing_dot" $f64_dec.trailing_dot) 137 | ) 138 | 139 | (assert_return (invoke "f32.nan") (i32.const 0x7fc00000)) 140 | (assert_return (invoke "f32.positive_nan") (i32.const 0x7fc00000)) 141 | (assert_return (invoke "f32.negative_nan") (i32.const 0xffc00000)) 142 | (assert_return (invoke "f32.plain_nan") (i32.const 0x7fc00000)) 143 | (assert_return (invoke "f32.informally_known_as_plain_snan") (i32.const 0x7fa00000)) 144 | (assert_return (invoke "f32.allones_nan") (i32.const 0xffffffff)) 145 | (assert_return (invoke "f32.misc_nan") (i32.const 0x7f812345)) 146 | (assert_return (invoke "f32.misc_positive_nan") (i32.const 0x7fb04050)) 147 | (assert_return (invoke "f32.misc_negative_nan") (i32.const 0xffaabcde)) 148 | (assert_return (invoke "f32.infinity") (i32.const 0x7f800000)) 149 | (assert_return (invoke "f32.positive_infinity") (i32.const 0x7f800000)) 150 | (assert_return (invoke "f32.negative_infinity") (i32.const 0xff800000)) 151 | (assert_return (invoke "f32.zero") (i32.const 0)) 152 | (assert_return (invoke "f32.positive_zero") (i32.const 0)) 153 | (assert_return (invoke "f32.negative_zero") (i32.const 0x80000000)) 154 | (assert_return (invoke "f32.misc") (i32.const 0x40c90fdb)) 155 | (assert_return (invoke "f32.min_positive") (i32.const 1)) 156 | (assert_return (invoke "f32.min_normal") (i32.const 0x800000)) 157 | (assert_return (invoke "f32.max_subnormal") (i32.const 0x7fffff)) 158 | (assert_return (invoke "f32.max_finite") (i32.const 0x7f7fffff)) 159 | (assert_return (invoke "f32.trailing_dot") (i32.const 0x44800000)) 160 | (assert_return (invoke "f32_dec.zero") (i32.const 0)) 161 | (assert_return (invoke "f32_dec.positive_zero") (i32.const 0)) 162 | (assert_return (invoke "f32_dec.negative_zero") (i32.const 0x80000000)) 163 | (assert_return (invoke "f32_dec.misc") (i32.const 0x40c90fdb)) 164 | (assert_return (invoke "f32_dec.min_positive") (i32.const 1)) 165 | (assert_return (invoke "f32_dec.min_normal") (i32.const 0x800000)) 166 | (assert_return (invoke "f32_dec.max_subnormal") (i32.const 0x7fffff)) 167 | (assert_return (invoke "f32_dec.max_finite") (i32.const 0x7f7fffff)) 168 | (assert_return (invoke "f32_dec.trailing_dot") (i32.const 0x501502f9)) 169 | 170 | (assert_return (invoke "f64.nan") (i64.const 0x7ff8000000000000)) 171 | (assert_return (invoke "f64.positive_nan") (i64.const 0x7ff8000000000000)) 172 | (assert_return (invoke "f64.negative_nan") (i64.const 0xfff8000000000000)) 173 | (assert_return (invoke "f64.plain_nan") (i64.const 0x7ff8000000000000)) 174 | (assert_return (invoke "f64.informally_known_as_plain_snan") (i64.const 0x7ff4000000000000)) 175 | (assert_return (invoke "f64.allones_nan") (i64.const 0xffffffffffffffff)) 176 | (assert_return (invoke "f64.misc_nan") (i64.const 0x7ff0123456789abc)) 177 | (assert_return (invoke "f64.misc_positive_nan") (i64.const 0x7ff3040506070809)) 178 | (assert_return (invoke "f64.misc_negative_nan") (i64.const 0xfff2abcdef012345)) 179 | (assert_return (invoke "f64.infinity") (i64.const 0x7ff0000000000000)) 180 | (assert_return (invoke "f64.positive_infinity") (i64.const 0x7ff0000000000000)) 181 | (assert_return (invoke "f64.negative_infinity") (i64.const 0xfff0000000000000)) 182 | (assert_return (invoke "f64.zero") (i64.const 0)) 183 | (assert_return (invoke "f64.positive_zero") (i64.const 0)) 184 | (assert_return (invoke "f64.negative_zero") (i64.const 0x8000000000000000)) 185 | (assert_return (invoke "f64.misc") (i64.const 0x401921fb54442d18)) 186 | (assert_return (invoke "f64.min_positive") (i64.const 1)) 187 | (assert_return (invoke "f64.min_normal") (i64.const 0x10000000000000)) 188 | (assert_return (invoke "f64.max_subnormal") (i64.const 0xfffffffffffff)) 189 | (assert_return (invoke "f64.max_finite") (i64.const 0x7fefffffffffffff)) 190 | (assert_return (invoke "f64.trailing_dot") (i64.const 0x4630000000000000)) 191 | (assert_return (invoke "f64_dec.zero") (i64.const 0)) 192 | (assert_return (invoke "f64_dec.positive_zero") (i64.const 0)) 193 | (assert_return (invoke "f64_dec.negative_zero") (i64.const 0x8000000000000000)) 194 | (assert_return (invoke "f64_dec.misc") (i64.const 0x401921fb54442d18)) 195 | (assert_return (invoke "f64_dec.min_positive") (i64.const 1)) 196 | (assert_return (invoke "f64_dec.min_normal") (i64.const 0x10000000000000)) 197 | (assert_return (invoke "f64_dec.max_subnormal") (i64.const 0xfffffffffffff)) 198 | (assert_return (invoke "f64_dec.max_finite") (i64.const 0x7fefffffffffffff)) 199 | (assert_return (invoke "f64_dec.trailing_dot") (i64.const 0x54b249ad2594c37d)) 200 | -------------------------------------------------------------------------------- /test/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 1 1 (segment 0 "\00\00\a0\7f")) 7 | 8 | (func $f32.load (result f32) (f32.load (i32.const 0))) 9 | (export "f32.load" $f32.load) 10 | 11 | (func $i32.load (result i32) (i32.load (i32.const 0))) 12 | (export "i32.load" $i32.load) 13 | 14 | (func $f32.store (f32.store (i32.const 0) (f32.const nan:0x200000))) 15 | (export "f32.store" $f32.store) 16 | 17 | (func $i32.store (i32.store (i32.const 0) (i32.const 0x7fa00000))) 18 | (export "i32.store" $i32.store) 19 | 20 | (func $reset (i32.store (i32.const 0) (i32.const 0))) 21 | (export "reset" $reset) 22 | ) 23 | 24 | (assert_return (invoke "i32.load") (i32.const 0x7fa00000)) 25 | (assert_return (invoke "f32.load") (f32.const nan:0x200000)) 26 | (invoke "reset") 27 | (assert_return (invoke "i32.load") (i32.const 0x0)) 28 | (assert_return (invoke "f32.load") (f32.const 0.0)) 29 | (invoke "f32.store") 30 | (assert_return (invoke "i32.load") (i32.const 0x7fa00000)) 31 | (assert_return (invoke "f32.load") (f32.const nan:0x200000)) 32 | (invoke "reset") 33 | (assert_return (invoke "i32.load") (i32.const 0x0)) 34 | (assert_return (invoke "f32.load") (f32.const 0.0)) 35 | (invoke "i32.store") 36 | (assert_return (invoke "i32.load") (i32.const 0x7fa00000)) 37 | (assert_return (invoke "f32.load") (f32.const nan:0x200000)) 38 | 39 | (module 40 | (memory 1 1 (segment 0 "\00\00\00\00\00\00\f4\7f")) 41 | 42 | (func $f64.load (result f64) (f64.load (i32.const 0))) 43 | (export "f64.load" $f64.load) 44 | 45 | (func $i64.load (result i64) (i64.load (i32.const 0))) 46 | (export "i64.load" $i64.load) 47 | 48 | (func $f64.store (f64.store (i32.const 0) (f64.const nan:0x4000000000000))) 49 | (export "f64.store" $f64.store) 50 | 51 | (func $i64.store (i64.store (i32.const 0) (i64.const 0x7ff4000000000000))) 52 | (export "i64.store" $i64.store) 53 | 54 | (func $reset (i64.store (i32.const 0) (i64.const 0))) 55 | (export "reset" $reset) 56 | ) 57 | 58 | (assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) 59 | (assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) 60 | (invoke "reset") 61 | (assert_return (invoke "i64.load") (i64.const 0x0)) 62 | (assert_return (invoke "f64.load") (f64.const 0.0)) 63 | (invoke "f64.store") 64 | (assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) 65 | (assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) 66 | (invoke "reset") 67 | (assert_return (invoke "i64.load") (i64.const 0x0)) 68 | (assert_return (invoke "f64.load") (f64.const 0.0)) 69 | (invoke "i64.store") 70 | (assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) 71 | (assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) 72 | 73 | ;; Test that unaligned load and store do not canonicalize NaNs. 74 | 75 | (module 76 | (memory 1 1 (segment 1 "\00\00\a0\7f")) 77 | 78 | (func $f32.load (result f32) (f32.load (i32.const 1))) 79 | (export "f32.load" $f32.load) 80 | 81 | (func $i32.load (result i32) (i32.load (i32.const 1))) 82 | (export "i32.load" $i32.load) 83 | 84 | (func $f32.store (f32.store (i32.const 1) (f32.const nan:0x200000))) 85 | (export "f32.store" $f32.store) 86 | 87 | (func $i32.store (i32.store (i32.const 1) (i32.const 0x7fa00000))) 88 | (export "i32.store" $i32.store) 89 | 90 | (func $reset (i32.store (i32.const 1) (i32.const 0))) 91 | (export "reset" $reset) 92 | ) 93 | 94 | (assert_return (invoke "i32.load") (i32.const 0x7fa00000)) 95 | (assert_return (invoke "f32.load") (f32.const nan:0x200000)) 96 | (invoke "reset") 97 | (assert_return (invoke "i32.load") (i32.const 0x0)) 98 | (assert_return (invoke "f32.load") (f32.const 0.0)) 99 | (invoke "f32.store") 100 | (assert_return (invoke "i32.load") (i32.const 0x7fa00000)) 101 | (assert_return (invoke "f32.load") (f32.const nan:0x200000)) 102 | (invoke "reset") 103 | (assert_return (invoke "i32.load") (i32.const 0x0)) 104 | (assert_return (invoke "f32.load") (f32.const 0.0)) 105 | (invoke "i32.store") 106 | (assert_return (invoke "i32.load") (i32.const 0x7fa00000)) 107 | (assert_return (invoke "f32.load") (f32.const nan:0x200000)) 108 | 109 | (module 110 | (memory 1 1 (segment 1 "\00\00\00\00\00\00\f4\7f")) 111 | 112 | (func $f64.load (result f64) (f64.load (i32.const 1))) 113 | (export "f64.load" $f64.load) 114 | 115 | (func $i64.load (result i64) (i64.load (i32.const 1))) 116 | (export "i64.load" $i64.load) 117 | 118 | (func $f64.store (f64.store (i32.const 1) (f64.const nan:0x4000000000000))) 119 | (export "f64.store" $f64.store) 120 | 121 | (func $i64.store (i64.store (i32.const 1) (i64.const 0x7ff4000000000000))) 122 | (export "i64.store" $i64.store) 123 | 124 | (func $reset (i64.store (i32.const 1) (i64.const 0))) 125 | (export "reset" $reset) 126 | ) 127 | 128 | (assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) 129 | (assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) 130 | (invoke "reset") 131 | (assert_return (invoke "i64.load") (i64.const 0x0)) 132 | (assert_return (invoke "f64.load") (f64.const 0.0)) 133 | (invoke "f64.store") 134 | (assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) 135 | (assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) 136 | (invoke "reset") 137 | (assert_return (invoke "i64.load") (i64.const 0x0)) 138 | (assert_return (invoke "f64.load") (f64.const 0.0)) 139 | (invoke "i64.store") 140 | (assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) 141 | (assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) 142 | 143 | ;; Test that load and store do not canonicalize NaNs as some JS engines do. 144 | 145 | (module 146 | (memory 1 1 (segment 0 "\01\00\d0\7f")) 147 | 148 | (func $f32.load (result f32) (f32.load (i32.const 0))) 149 | (export "f32.load" $f32.load) 150 | 151 | (func $i32.load (result i32) (i32.load (i32.const 0))) 152 | (export "i32.load" $i32.load) 153 | 154 | (func $f32.store (f32.store (i32.const 0) (f32.const nan:0x500001))) 155 | (export "f32.store" $f32.store) 156 | 157 | (func $i32.store (i32.store (i32.const 0) (i32.const 0x7fd00001))) 158 | (export "i32.store" $i32.store) 159 | 160 | (func $reset (i32.store (i32.const 0) (i32.const 0))) 161 | (export "reset" $reset) 162 | ) 163 | 164 | (assert_return (invoke "i32.load") (i32.const 0x7fd00001)) 165 | (assert_return (invoke "f32.load") (f32.const nan:0x500001)) 166 | (invoke "reset") 167 | (assert_return (invoke "i32.load") (i32.const 0x0)) 168 | (assert_return (invoke "f32.load") (f32.const 0.0)) 169 | (invoke "f32.store") 170 | (assert_return (invoke "i32.load") (i32.const 0x7fd00001)) 171 | (assert_return (invoke "f32.load") (f32.const nan:0x500001)) 172 | (invoke "reset") 173 | (assert_return (invoke "i32.load") (i32.const 0x0)) 174 | (assert_return (invoke "f32.load") (f32.const 0.0)) 175 | (invoke "i32.store") 176 | (assert_return (invoke "i32.load") (i32.const 0x7fd00001)) 177 | (assert_return (invoke "f32.load") (f32.const nan:0x500001)) 178 | 179 | (module 180 | (memory 1 1 (segment 0 "\01\00\00\00\00\00\fc\7f")) 181 | 182 | (func $f64.load (result f64) (f64.load (i32.const 0))) 183 | (export "f64.load" $f64.load) 184 | 185 | (func $i64.load (result i64) (i64.load (i32.const 0))) 186 | (export "i64.load" $i64.load) 187 | 188 | (func $f64.store (f64.store (i32.const 0) (f64.const nan:0xc000000000001))) 189 | (export "f64.store" $f64.store) 190 | 191 | (func $i64.store (i64.store (i32.const 0) (i64.const 0x7ffc000000000001))) 192 | (export "i64.store" $i64.store) 193 | 194 | (func $reset (i64.store (i32.const 0) (i64.const 0))) 195 | (export "reset" $reset) 196 | ) 197 | 198 | (assert_return (invoke "i64.load") (i64.const 0x7ffc000000000001)) 199 | (assert_return (invoke "f64.load") (f64.const nan:0xc000000000001)) 200 | (invoke "reset") 201 | (assert_return (invoke "i64.load") (i64.const 0x0)) 202 | (assert_return (invoke "f64.load") (f64.const 0.0)) 203 | (invoke "f64.store") 204 | (assert_return (invoke "i64.load") (i64.const 0x7ffc000000000001)) 205 | (assert_return (invoke "f64.load") (f64.const nan:0xc000000000001)) 206 | (invoke "reset") 207 | (assert_return (invoke "i64.load") (i64.const 0x0)) 208 | (assert_return (invoke "f64.load") (f64.const 0.0)) 209 | (invoke "i64.store") 210 | (assert_return (invoke "i64.load") (i64.const 0x7ffc000000000001)) 211 | (assert_return (invoke "f64.load") (f64.const nan:0xc000000000001)) 212 | -------------------------------------------------------------------------------- /test/forward.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (export "even" $even) 3 | (export "odd" $odd) 4 | 5 | (func $even (param $n i32) (result i32) 6 | (if (i32.eq (get_local $n) (i32.const 0)) 7 | (i32.const 1) 8 | (call $odd (i32.sub (get_local $n) (i32.const 1))) 9 | ) 10 | ) 11 | 12 | (func $odd (param $n i32) (result i32) 13 | (if (i32.eq (get_local $n) (i32.const 0)) 14 | (i32.const 0) 15 | (call $even (i32.sub (get_local $n) (i32.const 1))) 16 | ) 17 | ) 18 | ) 19 | 20 | (assert_return (invoke "even" (i32.const 13)) (i32.const 0)) 21 | (assert_return (invoke "even" (i32.const 20)) (i32.const 1)) 22 | (assert_return (invoke "odd" (i32.const 13)) (i32.const 1)) 23 | (assert_return (invoke "odd" (i32.const 20)) (i32.const 0)) 24 | -------------------------------------------------------------------------------- /test/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 (type 0)) 11 | (func (type $S)) 12 | 13 | (func $one (type 4) (i32.const 13)) 14 | (export "one" $one) 15 | 16 | (func $two (type $T) (i32.add (get_local 0) (i32.const 1))) 17 | (export "two" $two) 18 | 19 | ;; Both signature and parameters are allowed (and required to match) 20 | ;; since this allows the naming of parameters. 21 | (func $three (type $T) (param $a i32) (result i32) (i32.sub (get_local 0) (i32.const 2))) 22 | (export "three" $three) 23 | 24 | (import $print "spectest" "print" (type 6)) 25 | (func $four (type $U) (call_import $print (get_local 0))) 26 | (export "four" $four) 27 | ) 28 | (assert_return (invoke "one") (i32.const 13)) 29 | (assert_return (invoke "two" (i32.const 13)) (i32.const 14)) 30 | (assert_return (invoke "three" (i32.const 13)) (i32.const 11)) 31 | (invoke "four" (i32.const 83)) 32 | 33 | (assert_invalid (module (func (type 42))) "unknown function type 42") 34 | (assert_invalid (module (import "spectest" "print" (type 43))) "unknown function type 43") 35 | 36 | (module 37 | (type $T (func (param) (result i32))) 38 | (type $U (func (param) (result i32))) 39 | (table $t1 $t2 $t3 $u1 $u2 $t1 $t3) 40 | 41 | (func $t1 (type $T) (i32.const 1)) 42 | (func $t2 (type $T) (i32.const 2)) 43 | (func $t3 (type $T) (i32.const 3)) 44 | (func $u1 (type $U) (i32.const 4)) 45 | (func $u2 (type $U) (i32.const 5)) 46 | 47 | (func $callt (param $i i32) (result i32) 48 | (call_indirect $T (get_local $i)) 49 | ) 50 | (export "callt" $callt) 51 | 52 | (func $callu (param $i i32) (result i32) 53 | (call_indirect $U (get_local $i)) 54 | ) 55 | (export "callu" $callu) 56 | ) 57 | 58 | (assert_return (invoke "callt" (i32.const 0)) (i32.const 1)) 59 | (assert_return (invoke "callt" (i32.const 1)) (i32.const 2)) 60 | (assert_return (invoke "callt" (i32.const 2)) (i32.const 3)) 61 | (assert_trap (invoke "callt" (i32.const 3)) "indirect call signature mismatch") 62 | (assert_trap (invoke "callt" (i32.const 4)) "indirect call signature mismatch") 63 | (assert_return (invoke "callt" (i32.const 5)) (i32.const 1)) 64 | (assert_return (invoke "callt" (i32.const 6)) (i32.const 3)) 65 | (assert_trap (invoke "callt" (i32.const 7)) "undefined table index 7") 66 | (assert_trap (invoke "callt" (i32.const 100)) "undefined table index 100") 67 | (assert_trap (invoke "callt" (i32.const -1)) "undefined table index -1") 68 | 69 | (assert_trap (invoke "callu" (i32.const 0)) "indirect call signature mismatch") 70 | (assert_trap (invoke "callu" (i32.const 1)) "indirect call signature mismatch") 71 | (assert_trap (invoke "callu" (i32.const 2)) "indirect call signature mismatch") 72 | (assert_return (invoke "callu" (i32.const 3)) (i32.const 4)) 73 | (assert_return (invoke "callu" (i32.const 4)) (i32.const 5)) 74 | (assert_trap (invoke "callu" (i32.const 5)) "indirect call signature mismatch") 75 | (assert_trap (invoke "callu" (i32.const 6)) "indirect call signature mismatch") 76 | (assert_trap (invoke "callu" (i32.const 7)) "undefined table index 7") 77 | (assert_trap (invoke "callu" (i32.const -1)) "undefined table index -1") 78 | 79 | (module 80 | (type $T (func (result i32))) 81 | (table 0 1) 82 | 83 | (import $print_i32 "spectest" "print" (param i32)) 84 | 85 | (func $t1 (type $T) (i32.const 1)) 86 | (func $t2 (type $T) (i32.const 2)) 87 | 88 | (func $callt (param $i i32) (result i32) 89 | (call_indirect $T (get_local $i))) 90 | (export "callt" $callt) 91 | ) 92 | 93 | (assert_return (invoke "callt" (i32.const 0)) (i32.const 1)) 94 | (assert_return (invoke "callt" (i32.const 1)) (i32.const 2)) 95 | -------------------------------------------------------------------------------- /test/get_local.wast: -------------------------------------------------------------------------------- 1 | ;; Test `get_local` operator 2 | 3 | (module 4 | ;; Typing 5 | 6 | (func "type-local-i32" (result i32) (local i32) (get_local 0)) 7 | (func "type-local-i64" (result i64) (local i64) (get_local 0)) 8 | (func "type-local-f32" (result f32) (local f32) (get_local 0)) 9 | (func "type-local-f64" (result f64) (local f64) (get_local 0)) 10 | 11 | (func "type-param-i32" (param i32) (result i32) (get_local 0)) 12 | (func "type-param-i64" (param i64) (result i64) (get_local 0)) 13 | (func "type-param-f32" (param f32) (result f32) (get_local 0)) 14 | (func "type-param-f64" (param f64) (result f64) (get_local 0)) 15 | 16 | (func "type-mixed" (param i64 f32 f64 i32 i32) (result f64) 17 | (local f32 i64 i64 f64) 18 | (i64.eqz (get_local 0)) 19 | (f32.neg (get_local 1)) 20 | (f64.neg (get_local 2)) 21 | (i32.eqz (get_local 3)) 22 | (i32.eqz (get_local 4)) 23 | (f32.neg (get_local 5)) 24 | (i64.eqz (get_local 6)) 25 | (i64.eqz (get_local 7)) 26 | (f64.neg (get_local 8)) 27 | ) 28 | 29 | ;; Reading 30 | 31 | (func "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 | (f64.const -0) 79 | ) 80 | 81 | (assert_return 82 | (invoke "read" 83 | (i64.const 1) (f32.const 2) (f64.const 3.3) (i32.const 4) (i32.const 5) 84 | ) 85 | (f64.const 34.8) 86 | ) 87 | 88 | 89 | ;; Invalid typing of access to locals 90 | 91 | (assert_invalid 92 | (module (func $type-local-num-vs-num (result i64) (local i32) (get_local 0))) 93 | "type mismatch" 94 | ) 95 | (assert_invalid 96 | (module (func $type-local-num-vs-num (local f32) (i32.eqz (get_local 0)))) 97 | "type mismatch" 98 | ) 99 | (assert_invalid 100 | (module (func $type-local-num-vs-num (local f64 i64) (f64.neg (get_local 1)))) 101 | "type mismatch" 102 | ) 103 | 104 | 105 | ;; Invalid typing of access to parameters 106 | 107 | (assert_invalid 108 | (module (func $type-param-num-vs-num (param i32) (result i64) (get_local 0))) 109 | "type mismatch" 110 | ) 111 | (assert_invalid 112 | (module (func $type-param-num-vs-num (param f32) (i32.eqz (get_local 0)))) 113 | "type mismatch" 114 | ) 115 | (assert_invalid 116 | (module (func $type-param-num-vs-num (param f64 i64) (f64.neg (get_local 1)))) 117 | "type mismatch" 118 | ) 119 | 120 | 121 | ;; Invalid local index 122 | 123 | (assert_invalid 124 | (module (func $unbound-local (local i32 i64) (get_local 3))) 125 | "unknown local" 126 | ) 127 | (assert_invalid 128 | (module (func $large-local (local i32 i64) (get_local 14324343))) 129 | "unknown local" 130 | ) 131 | 132 | (assert_invalid 133 | (module (func $unbound-param (param i32 i64) (get_local 2))) 134 | "unknown local" 135 | ) 136 | (assert_invalid 137 | (module (func $large-param (local i32 i64) (get_local 714324343))) 138 | "unknown local" 139 | ) 140 | 141 | (assert_invalid 142 | (module (func $unbound-mixed (param i32) (local i32 i64) (get_local 3))) 143 | "unknown local" 144 | ) 145 | (assert_invalid 146 | (module (func $large-mixed (param i64) (local i32 i64) (get_local 214324343))) 147 | "unknown local" 148 | ) 149 | 150 | -------------------------------------------------------------------------------- /test/imports.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (import $print_i32 "spectest" "print" (param i32)) 3 | (import $print_i64 "spectest" "print" (param i64)) 4 | (import $print_i32_f32 "spectest" "print" (param i32 f32)) 5 | (import $print_i64_f64 "spectest" "print" (param i64 f64)) 6 | (func $print32 (param $i i32) 7 | (call_import $print_i32_f32 8 | (i32.add (get_local $i) (i32.const 1)) 9 | (f32.const 42) 10 | ) 11 | (call_import $print_i32 (get_local $i)) 12 | ) 13 | (func $print64 (param $i i64) 14 | (call_import $print_i64_f64 15 | (i64.add (get_local $i) (i64.const 1)) 16 | (f64.const 53) 17 | ) 18 | (call_import $print_i64 (get_local $i)) 19 | ) 20 | (export "print32" $print32) 21 | (export "print64" $print64) 22 | ) 23 | 24 | (assert_return (invoke "print32" (i32.const 13))) 25 | (assert_return (invoke "print64" (i64.const 24))) 26 | 27 | -------------------------------------------------------------------------------- /test/int_literals.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func $i32.test (result i32) (return (i32.const 0x0bAdD00D))) 3 | (func $i32.umax (result i32) (return (i32.const 0xffffffff))) 4 | (func $i32.smax (result i32) (return (i32.const 0x7fffffff))) 5 | (func $i32.neg_smax (result i32) (return (i32.const -0x7fffffff))) 6 | (func $i32.smin (result i32) (return (i32.const -0x80000000))) 7 | (func $i32.alt_smin (result i32) (return (i32.const 0x80000000))) 8 | (func $i32.inc_smin (result i32) (return (i32.add (i32.const -0x80000000) (i32.const 1)))) 9 | (func $i32.neg_zero (result i32) (return (i32.const -0x0))) 10 | (func $i32.not_octal (result i32) (return (i32.const 010))) 11 | (func $i32.unsigned_decimal (result i32) (return (i32.const 4294967295))) 12 | (func $i32.plus_sign (result i32) (return (i32.const +42))) 13 | 14 | (func $i64.test (result i64) (return (i64.const 0x0CABBA6E0ba66a6e))) 15 | (func $i64.umax (result i64) (return (i64.const 0xffffffffffffffff))) 16 | (func $i64.smax (result i64) (return (i64.const 0x7fffffffffffffff))) 17 | (func $i64.neg_smax (result i64) (return (i64.const -0x7fffffffffffffff))) 18 | (func $i64.smin (result i64) (return (i64.const -0x8000000000000000))) 19 | (func $i64.alt_smin (result i64) (return (i64.const 0x8000000000000000))) 20 | (func $i64.inc_smin (result i64) (return (i64.add (i64.const -0x8000000000000000) (i64.const 1)))) 21 | (func $i64.neg_zero (result i64) (return (i64.const -0x0))) 22 | (func $i64.not_octal (result i64) (return (i64.const 010))) 23 | (func $i64.unsigned_decimal (result i64) (return (i64.const 18446744073709551615))) 24 | (func $i64.plus_sign (result i64) (return (i64.const +42))) 25 | 26 | (export "i32.test" $i32.test) 27 | (export "i32.umax" $i32.umax) 28 | (export "i32.smax" $i32.smax) 29 | (export "i32.neg_smax" $i32.neg_smax) 30 | (export "i32.smin" $i32.smin) 31 | (export "i32.alt_smin" $i32.alt_smin) 32 | (export "i32.inc_smin" $i32.inc_smin) 33 | (export "i32.neg_zero" $i32.neg_zero) 34 | (export "i32.not_octal" $i32.not_octal) 35 | (export "i32.unsigned_decimal" $i32.unsigned_decimal) 36 | (export "i32.plus_sign" $i32.plus_sign) 37 | 38 | (export "i64.test" $i64.test) 39 | (export "i64.umax" $i64.umax) 40 | (export "i64.smax" $i64.smax) 41 | (export "i64.neg_smax" $i64.neg_smax) 42 | (export "i64.smin" $i64.smin) 43 | (export "i64.alt_smin" $i64.alt_smin) 44 | (export "i64.inc_smin" $i64.inc_smin) 45 | (export "i64.neg_zero" $i64.neg_zero) 46 | (export "i64.not_octal" $i64.not_octal) 47 | (export "i64.unsigned_decimal" $i64.unsigned_decimal) 48 | (export "i64.plus_sign" $i64.plus_sign) 49 | ) 50 | 51 | (assert_return (invoke "i32.test") (i32.const 195940365)) 52 | (assert_return (invoke "i32.umax") (i32.const -1)) 53 | (assert_return (invoke "i32.smax") (i32.const 2147483647)) 54 | (assert_return (invoke "i32.neg_smax") (i32.const -2147483647)) 55 | (assert_return (invoke "i32.smin") (i32.const -2147483648)) 56 | (assert_return (invoke "i32.alt_smin") (i32.const -2147483648)) 57 | (assert_return (invoke "i32.inc_smin") (i32.const -2147483647)) 58 | (assert_return (invoke "i32.neg_zero") (i32.const 0)) 59 | (assert_return (invoke "i32.not_octal") (i32.const 10)) 60 | (assert_return (invoke "i32.unsigned_decimal") (i32.const -1)) 61 | (assert_return (invoke "i32.plus_sign") (i32.const 42)) 62 | 63 | (assert_return (invoke "i64.test") (i64.const 913028331277281902)) 64 | (assert_return (invoke "i64.umax") (i64.const -1)) 65 | (assert_return (invoke "i64.smax") (i64.const 9223372036854775807)) 66 | (assert_return (invoke "i64.neg_smax") (i64.const -9223372036854775807)) 67 | (assert_return (invoke "i64.smin") (i64.const -9223372036854775808)) 68 | (assert_return (invoke "i64.alt_smin") (i64.const -9223372036854775808)) 69 | (assert_return (invoke "i64.inc_smin") (i64.const -9223372036854775807)) 70 | (assert_return (invoke "i64.neg_zero") (i64.const 0)) 71 | (assert_return (invoke "i64.not_octal") (i64.const 10)) 72 | (assert_return (invoke "i64.unsigned_decimal") (i64.const -1)) 73 | (assert_return (invoke "i64.plus_sign") (i64.const 42)) 74 | -------------------------------------------------------------------------------- /test/labels.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func $block (result i32) 3 | (block $exit 4 | (br $exit (i32.const 1)) 5 | (i32.const 0) 6 | ) 7 | ) 8 | 9 | (func $loop1 (result i32) 10 | (local $i i32) 11 | (set_local $i (i32.const 0)) 12 | (loop $exit $cont 13 | (set_local $i (i32.add (get_local $i) (i32.const 1))) 14 | (if (i32.eq (get_local $i) (i32.const 5)) 15 | (br $exit (get_local $i)) 16 | ) 17 | (br $cont) 18 | ) 19 | ) 20 | 21 | (func $loop2 (result i32) 22 | (local $i i32) 23 | (set_local $i (i32.const 0)) 24 | (loop $exit $cont 25 | (set_local $i (i32.add (get_local $i) (i32.const 1))) 26 | (if (i32.eq (get_local $i) (i32.const 5)) 27 | (br $cont) 28 | ) 29 | (if (i32.eq (get_local $i) (i32.const 8)) 30 | (br $exit (get_local $i)) 31 | ) 32 | (set_local $i (i32.add (get_local $i) (i32.const 1))) 33 | (br $cont) 34 | ) 35 | ) 36 | 37 | (func $loop3 (result i32) 38 | (local $i i32) 39 | (set_local $i (i32.const 0)) 40 | (loop $exit $cont 41 | (set_local $i (i32.add (get_local $i) (i32.const 1))) 42 | (if (i32.eq (get_local $i) (i32.const 5)) 43 | (br $exit (get_local $i)) 44 | ) 45 | (get_local $i) 46 | ) 47 | ) 48 | 49 | (func $loop4 (param $max i32) (result i32) 50 | (local $i i32) 51 | (set_local $i (i32.const 1)) 52 | (loop $exit $cont 53 | (set_local $i (i32.add (get_local $i) (get_local $i))) 54 | (if (i32.gt_u (get_local $i) (get_local $max)) 55 | (br $exit (get_local $i)) 56 | ) 57 | (br $cont) 58 | ) 59 | ) 60 | 61 | (func $loop5 (result i32) 62 | (i32.add (loop $l0 $l1 63 | (i32.const 1) 64 | ) 65 | (i32.const 1) 66 | ) 67 | ) 68 | 69 | (func $if (result i32) 70 | (local $i i32) 71 | (set_local $i (i32.const 0)) 72 | (block 73 | (if 74 | (i32.const 1) 75 | (then $l (br $l) (set_local $i (i32.const 666))) 76 | ) 77 | (set_local $i (i32.add (get_local $i) (i32.const 1))) 78 | (if 79 | (i32.const 1) 80 | (then $l (br $l) (set_local $i (i32.const 666))) 81 | (else (set_local $i (i32.const 888))) 82 | ) 83 | (set_local $i (i32.add (get_local $i) (i32.const 1))) 84 | (if 85 | (i32.const 1) 86 | (then $l (br $l) (set_local $i (i32.const 666))) 87 | (else $l (set_local $i (i32.const 888))) 88 | ) 89 | (set_local $i (i32.add (get_local $i) (i32.const 1))) 90 | (if 91 | (i32.const 0) 92 | (then (set_local $i (i32.const 888))) 93 | (else $l (br $l) (set_local $i (i32.const 666))) 94 | ) 95 | (set_local $i (i32.add (get_local $i) (i32.const 1))) 96 | (if 97 | (i32.const 0) 98 | (then $l (set_local $i (i32.const 888))) 99 | (else $l (br $l) (set_local $i (i32.const 666))) 100 | ) 101 | (set_local $i (i32.add (get_local $i) (i32.const 1))) 102 | ) 103 | (get_local $i) 104 | ) 105 | 106 | (func $if2 (result i32) 107 | (local $i i32) 108 | (set_local $i (i32.const 0)) 109 | (block 110 | (if 111 | (i32.const 1) 112 | (then (br 0) (set_local $i (i32.const 666))) 113 | ) 114 | (set_local $i (i32.add (get_local $i) (i32.const 1))) 115 | (if 116 | (i32.const 1) 117 | (then (br 0) (set_local $i (i32.const 666))) 118 | (else (set_local $i (i32.const 888))) 119 | ) 120 | (set_local $i (i32.add (get_local $i) (i32.const 1))) 121 | (if 122 | (i32.const 1) 123 | (then (br 0) (set_local $i (i32.const 666))) 124 | (else (set_local $i (i32.const 888))) 125 | ) 126 | (set_local $i (i32.add (get_local $i) (i32.const 1))) 127 | (if 128 | (i32.const 0) 129 | (then (set_local $i (i32.const 888))) 130 | (else (br 0) (set_local $i (i32.const 666))) 131 | ) 132 | (set_local $i (i32.add (get_local $i) (i32.const 1))) 133 | (if 134 | (i32.const 0) 135 | (then (set_local $i (i32.const 888))) 136 | (else (br 0) (set_local $i (i32.const 666))) 137 | ) 138 | (set_local $i (i32.add (get_local $i) (i32.const 1))) 139 | ) 140 | (get_local $i) 141 | ) 142 | 143 | (func $switch (param i32) (result i32) 144 | (block $ret 145 | (i32.mul (i32.const 10) 146 | (block $exit 147 | (block $0 148 | (block $default 149 | (block $3 150 | (block $2 151 | (block $1 152 | (br_table $0 $1 $2 $3 $default (get_local 0)) 153 | ) ;; 1 154 | (i32.const 1) 155 | ) ;; 2 156 | (br $exit (i32.const 2)) 157 | ) ;; 3 158 | (br $ret (i32.const 3)) 159 | ) ;; default 160 | (i32.const 4) 161 | ) ;; 0 162 | (i32.const 5) 163 | ) 164 | ) 165 | ) 166 | ) 167 | 168 | (func $return (param i32) (result i32) 169 | (block $default 170 | (block $1 171 | (block $0 172 | (br_table $0 $1 (get_local 0)) 173 | (br $default) 174 | ) ;; 0 175 | (return (i32.const 0)) 176 | ) ;; 1 177 | (i32.const 1) 178 | ) ;; default 179 | (i32.const 2) 180 | ) 181 | 182 | (func $br_if0 (result i32) 183 | (local $i i32) 184 | (set_local $i (i32.const 0)) 185 | (block $outer 186 | (block $inner 187 | (br_if $inner (i32.const 0)) 188 | (set_local $i (i32.or (get_local $i) (i32.const 0x1))) 189 | (br_if $inner (i32.const 1)) 190 | (set_local $i (i32.or (get_local $i) (i32.const 0x2))) 191 | ) 192 | (br_if $outer 193 | (set_local $i (i32.or (get_local $i) (i32.const 0x4))) (i32.const 0) 194 | ) 195 | (set_local $i (i32.or (get_local $i) (i32.const 0x8))) 196 | (br_if $outer 197 | (set_local $i (i32.or (get_local $i) (i32.const 0x10))) (i32.const 1) 198 | ) 199 | (set_local $i (i32.or (get_local $i) (i32.const 0x20))) 200 | ) 201 | ) 202 | 203 | (func $br_if1 (result i32) 204 | (block $l0 205 | (br_if $l0 (block $l1 (br $l1 (i32.const 1))) (i32.const 1)) 206 | (i32.const 1))) 207 | 208 | (func $br_if2 (result i32) 209 | (block $l0 210 | (if (i32.const 1) 211 | (br $l0 212 | (block $l1 213 | (br $l1 (i32.const 1))))) 214 | (i32.const 1))) 215 | 216 | (func $br_if3 (result i32) 217 | (local $i1 i32) 218 | (i32.add 219 | (block $l0 220 | (br_if $l0 (set_local $i1 (i32.const 1)) (set_local $i1 (i32.const 2))) 221 | (i32.const 0) 222 | ) 223 | (i32.const 0) 224 | ) 225 | (get_local $i1) 226 | ) 227 | 228 | (func $br_if4 229 | (block $l0 (br_if $l0 (nop) (i32.const 1))) 230 | ) 231 | 232 | (func $br (result i32) 233 | (block $l0 234 | (if (i32.const 1) 235 | (br $l0 (block $l1 (br $l1 (i32.const 1)))) 236 | (block (block $l1 (br $l1 (i32.const 1))) (nop)) 237 | ) 238 | (i32.const 1) 239 | ) 240 | ) 241 | 242 | (func $misc1 (result i32) 243 | (block $l1 (i32.xor (br $l1 (i32.const 1)) (i32.const 2))) 244 | ) 245 | 246 | (func $misc2 (result i32) 247 | (i32.xor (return (i32.const 1)) (i32.const 2)) 248 | ) 249 | 250 | (func $redefinition (result i32) 251 | (block $l1 252 | (i32.add (block $l1 253 | (i32.const 2)) 254 | (block $l1 255 | (br $l1 (i32.const 3))))) 256 | ) 257 | 258 | (export "block" $block) 259 | (export "loop1" $loop1) 260 | (export "loop2" $loop2) 261 | (export "loop3" $loop3) 262 | (export "loop4" $loop4) 263 | (export "loop5" $loop5) 264 | (export "if" $if) 265 | (export "if2" $if2) 266 | (export "switch" $switch) 267 | (export "return" $return) 268 | (export "br_if0" $br_if0) 269 | (export "br_if1" $br_if1) 270 | (export "br_if2" $br_if2) 271 | (export "br_if3" $br_if3) 272 | (export "br_if4" $br_if4) 273 | (export "br" $br) 274 | (export "misc1" $misc1) 275 | (export "misc2" $misc2) 276 | (export "redefinition" $redefinition) 277 | ) 278 | 279 | (assert_return (invoke "block") (i32.const 1)) 280 | (assert_return (invoke "loop1") (i32.const 5)) 281 | (assert_return (invoke "loop2") (i32.const 8)) 282 | (assert_return (invoke "loop3") (i32.const 1)) 283 | (assert_return (invoke "loop4" (i32.const 8)) (i32.const 16)) 284 | (assert_return (invoke "loop5") (i32.const 2)) 285 | (assert_return (invoke "if") (i32.const 5)) 286 | (assert_return (invoke "if2") (i32.const 5)) 287 | (assert_return (invoke "switch" (i32.const 0)) (i32.const 50)) 288 | (assert_return (invoke "switch" (i32.const 1)) (i32.const 20)) 289 | (assert_return (invoke "switch" (i32.const 2)) (i32.const 20)) 290 | (assert_return (invoke "switch" (i32.const 3)) (i32.const 3)) 291 | (assert_return (invoke "switch" (i32.const 4)) (i32.const 50)) 292 | (assert_return (invoke "switch" (i32.const 5)) (i32.const 50)) 293 | (assert_return (invoke "return" (i32.const 0)) (i32.const 0)) 294 | (assert_return (invoke "return" (i32.const 1)) (i32.const 2)) 295 | (assert_return (invoke "return" (i32.const 2)) (i32.const 2)) 296 | (assert_return (invoke "br_if0") (i32.const 0x1d)) 297 | (assert_return (invoke "br_if1") (i32.const 1)) 298 | (assert_return (invoke "br_if2") (i32.const 1)) 299 | (assert_return (invoke "br_if3") (i32.const 2)) 300 | (assert_return (invoke "br_if4")) 301 | (assert_return (invoke "br") (i32.const 1)) 302 | (assert_return (invoke "misc1") (i32.const 1)) 303 | (assert_return (invoke "misc2") (i32.const 1)) 304 | (assert_return (invoke "redefinition") (i32.const 5)) 305 | 306 | (assert_invalid 307 | (module (func (block $l (f32.neg (br_if $l (i32.const 1))) (nop)))) 308 | "type mismatch" 309 | ) 310 | (assert_invalid 311 | (module (func (result f32) (block $l (br_if $l (f32.const 0) (i32.const 1))))) 312 | "type mismatch" 313 | ) 314 | (assert_invalid 315 | (module (func (result i32) (block $l (br_if $l (f32.const 0) (i32.const 1))))) 316 | "type mismatch" 317 | ) 318 | (assert_invalid 319 | (module (func (block $l (f32.neg (br_if $l (f32.const 0) (i32.const 1)))))) 320 | "type mismatch" 321 | ) 322 | (assert_invalid 323 | (module 324 | (func (param i32) (result i32) 325 | (block $l (f32.neg (br_if $l (f32.const 0) (get_local 0)))) 326 | ) 327 | ) 328 | "type mismatch" 329 | ) 330 | (assert_invalid 331 | (module 332 | (func (param i32) (result f32) 333 | (block $l (f32.neg (block $i (br_if $l (f32.const 3) (get_local 0))))) 334 | ) 335 | ) 336 | "type mismatch" 337 | ) 338 | -------------------------------------------------------------------------------- /test/memory.wast: -------------------------------------------------------------------------------- 1 | ;; Test memory section structure 2 | (module (memory 0 0)) 3 | (module (memory 0 1)) 4 | (module (memory 1 256)) 5 | (module (memory 0 65535)) 6 | (module (memory 0 0 (segment 0 ""))) 7 | (module (memory 1 1 (segment 0 "a"))) 8 | (module (memory 1 2 (segment 0 "a") (segment 65535 "b"))) 9 | (module (memory 1 2 (segment 0 "a") (segment 1 "b") (segment 2 "c"))) 10 | 11 | (assert_invalid 12 | (module (memory 1 0)) 13 | "minimum memory pages must be less than or equal to the maximum" 14 | ) 15 | (assert_invalid 16 | (module (memory 0 0 (segment 0 "a"))) 17 | "data segment does not fit memory" 18 | ) 19 | (assert_invalid 20 | (module (memory 1 2 (segment 0 "a") (segment 98304 "b"))) 21 | "data segment does not fit memory" 22 | ) 23 | (assert_invalid 24 | (module (memory 1 2 (segment 0 "abc") (segment 0 "def"))) 25 | "data segment not disjoint and ordered" 26 | ) 27 | (assert_invalid 28 | (module (memory 1 2 (segment 3 "ab") (segment 0 "de"))) 29 | "data segment not disjoint and ordered" 30 | ) 31 | (assert_invalid 32 | (module (memory 1 2 (segment 0 "a") (segment 2 "b") (segment 1 "c"))) 33 | "data segment not disjoint and ordered" 34 | ) 35 | (assert_invalid 36 | (module (memory 0 65536)) 37 | "linear memory pages must be less or equal to 65535 (4GiB)" 38 | ) 39 | (assert_invalid 40 | (module (memory 0 2147483648)) 41 | "linear memory pages must be less or equal to 65535 (4GiB)" 42 | ) 43 | (assert_invalid 44 | (module (memory 0 4294967296)) 45 | "linear memory pages must be less or equal to 65535 (4GiB)" 46 | ) 47 | 48 | ;; Test alignment annotation rules 49 | (module (memory 0) (func (i32.load8_u align=2 (i32.const 0)))) 50 | (module (memory 0) (func (i32.load16_u align=4 (i32.const 0)))) 51 | (module (memory 0) (func (i32.load align=8 (i32.const 0)))) 52 | (module (memory 0) (func (f32.load align=8 (i32.const 0)))) 53 | 54 | (assert_invalid 55 | (module (memory 0) (func (i64.load align=0 (i32.const 0)))) 56 | "non-power-of-two alignment" 57 | ) 58 | (assert_invalid 59 | (module (memory 0) (func (i64.load align=3 (i32.const 0)))) 60 | "non-power-of-two alignment" 61 | ) 62 | (assert_invalid 63 | (module (memory 0) (func (i64.load align=5 (i32.const 0)))) 64 | "non-power-of-two alignment" 65 | ) 66 | (assert_invalid 67 | (module (memory 0) (func (i64.load align=6 (i32.const 0)))) 68 | "non-power-of-two alignment" 69 | ) 70 | (assert_invalid 71 | (module (memory 0) (func (i64.load align=7 (i32.const 0)))) 72 | "non-power-of-two alignment" 73 | ) 74 | 75 | (module 76 | (memory 1 (segment 0 "ABC\a7D") (segment 20 "WASM")) 77 | 78 | ;; Data section 79 | (func $data (result i32) 80 | (i32.and 81 | (i32.and 82 | (i32.and 83 | (i32.eq (i32.load8_u (i32.const 0)) (i32.const 65)) 84 | (i32.eq (i32.load8_u (i32.const 3)) (i32.const 167)) 85 | ) 86 | (i32.and 87 | (i32.eq (i32.load8_u (i32.const 6)) (i32.const 0)) 88 | (i32.eq (i32.load8_u (i32.const 19)) (i32.const 0)) 89 | ) 90 | ) 91 | (i32.and 92 | (i32.and 93 | (i32.eq (i32.load8_u (i32.const 20)) (i32.const 87)) 94 | (i32.eq (i32.load8_u (i32.const 23)) (i32.const 77)) 95 | ) 96 | (i32.and 97 | (i32.eq (i32.load8_u (i32.const 24)) (i32.const 0)) 98 | (i32.eq (i32.load8_u (i32.const 1023)) (i32.const 0)) 99 | ) 100 | ) 101 | ) 102 | ) 103 | 104 | ;; Aligned read/write 105 | (func $aligned (result i32) 106 | (local i32 i32 i32) 107 | (set_local 0 (i32.const 10)) 108 | (loop 109 | (if 110 | (i32.eq (get_local 0) (i32.const 0)) 111 | (br 2) 112 | ) 113 | (set_local 2 (i32.mul (get_local 0) (i32.const 4))) 114 | (i32.store (get_local 2) (get_local 0)) 115 | (set_local 1 (i32.load (get_local 2))) 116 | (if 117 | (i32.ne (get_local 0) (get_local 1)) 118 | (return (i32.const 0)) 119 | ) 120 | (set_local 0 (i32.sub (get_local 0) (i32.const 1))) 121 | (br 0) 122 | ) 123 | (i32.const 1) 124 | ) 125 | 126 | ;; Unaligned read/write 127 | (func $unaligned (result i32) 128 | (local i32 f64 f64) 129 | (set_local 0 (i32.const 10)) 130 | (loop 131 | (if 132 | (i32.eq (get_local 0) (i32.const 0)) 133 | (br 2) 134 | ) 135 | (set_local 2 (f64.convert_s/i32 (get_local 0))) 136 | (f64.store align=1 (get_local 0) (get_local 2)) 137 | (set_local 1 (f64.load align=1 (get_local 0))) 138 | (if 139 | (f64.ne (get_local 2) (get_local 1)) 140 | (return (i32.const 0)) 141 | ) 142 | (set_local 0 (i32.sub (get_local 0) (i32.const 1))) 143 | (br 0) 144 | ) 145 | (i32.const 1) 146 | ) 147 | 148 | ;; Memory cast 149 | (func $cast (result f64) 150 | (i64.store (i32.const 8) (i64.const -12345)) 151 | (if 152 | (f64.eq 153 | (f64.load (i32.const 8)) 154 | (f64.reinterpret/i64 (i64.const -12345)) 155 | ) 156 | (return (f64.const 0)) 157 | ) 158 | (i64.store align=1 (i32.const 9) (i64.const 0)) 159 | (i32.store16 align=1 (i32.const 15) (i32.const 16453)) 160 | (f64.load align=1 (i32.const 9)) 161 | ) 162 | 163 | ;; Sign and zero extending memory loads 164 | (func $i32_load8_s (param $i i32) (result i32) 165 | (i32.store8 (i32.const 8) (get_local $i)) 166 | (i32.load8_s (i32.const 8)) 167 | ) 168 | (func $i32_load8_u (param $i i32) (result i32) 169 | (i32.store8 (i32.const 8) (get_local $i)) 170 | (i32.load8_u (i32.const 8)) 171 | ) 172 | (func $i32_load16_s (param $i i32) (result i32) 173 | (i32.store16 (i32.const 8) (get_local $i)) 174 | (i32.load16_s (i32.const 8)) 175 | ) 176 | (func $i32_load16_u (param $i i32) (result i32) 177 | (i32.store16 (i32.const 8) (get_local $i)) 178 | (i32.load16_u (i32.const 8)) 179 | ) 180 | (func $i64_load8_s (param $i i64) (result i64) 181 | (i64.store8 (i32.const 8) (get_local $i)) 182 | (i64.load8_s (i32.const 8)) 183 | ) 184 | (func $i64_load8_u (param $i i64) (result i64) 185 | (i64.store8 (i32.const 8) (get_local $i)) 186 | (i64.load8_u (i32.const 8)) 187 | ) 188 | (func $i64_load16_s (param $i i64) (result i64) 189 | (i64.store16 (i32.const 8) (get_local $i)) 190 | (i64.load16_s (i32.const 8)) 191 | ) 192 | (func $i64_load16_u (param $i i64) (result i64) 193 | (i64.store16 (i32.const 8) (get_local $i)) 194 | (i64.load16_u (i32.const 8)) 195 | ) 196 | (func $i64_load32_s (param $i i64) (result i64) 197 | (i64.store32 (i32.const 8) (get_local $i)) 198 | (i64.load32_s (i32.const 8)) 199 | ) 200 | (func $i64_load32_u (param $i i64) (result i64) 201 | (i64.store32 (i32.const 8) (get_local $i)) 202 | (i64.load32_u (i32.const 8)) 203 | ) 204 | 205 | (export "data" $data) 206 | (export "aligned" $aligned) 207 | (export "unaligned" $unaligned) 208 | (export "cast" $cast) 209 | (export "i32_load8_s" $i32_load8_s) 210 | (export "i32_load8_u" $i32_load8_u) 211 | (export "i32_load16_s" $i32_load16_s) 212 | (export "i32_load16_u" $i32_load16_u) 213 | (export "i64_load8_s" $i64_load8_s) 214 | (export "i64_load8_u" $i64_load8_u) 215 | (export "i64_load16_s" $i64_load16_s) 216 | (export "i64_load16_u" $i64_load16_u) 217 | (export "i64_load32_s" $i64_load32_s) 218 | (export "i64_load32_u" $i64_load32_u) 219 | ) 220 | 221 | (assert_return (invoke "data") (i32.const 1)) 222 | (assert_return (invoke "aligned") (i32.const 1)) 223 | (assert_return (invoke "unaligned") (i32.const 1)) 224 | (assert_return (invoke "cast") (f64.const 42.0)) 225 | 226 | (assert_return (invoke "i32_load8_s" (i32.const -1)) (i32.const -1)) 227 | (assert_return (invoke "i32_load8_u" (i32.const -1)) (i32.const 255)) 228 | (assert_return (invoke "i32_load16_s" (i32.const -1)) (i32.const -1)) 229 | (assert_return (invoke "i32_load16_u" (i32.const -1)) (i32.const 65535)) 230 | 231 | (assert_return (invoke "i32_load8_s" (i32.const 100)) (i32.const 100)) 232 | (assert_return (invoke "i32_load8_u" (i32.const 200)) (i32.const 200)) 233 | (assert_return (invoke "i32_load16_s" (i32.const 20000)) (i32.const 20000)) 234 | (assert_return (invoke "i32_load16_u" (i32.const 40000)) (i32.const 40000)) 235 | 236 | (assert_return (invoke "i64_load8_s" (i64.const -1)) (i64.const -1)) 237 | (assert_return (invoke "i64_load8_u" (i64.const -1)) (i64.const 255)) 238 | (assert_return (invoke "i64_load16_s" (i64.const -1)) (i64.const -1)) 239 | (assert_return (invoke "i64_load16_u" (i64.const -1)) (i64.const 65535)) 240 | (assert_return (invoke "i64_load32_s" (i64.const -1)) (i64.const -1)) 241 | (assert_return (invoke "i64_load32_u" (i64.const -1)) (i64.const 4294967295)) 242 | 243 | (assert_return (invoke "i64_load8_s" (i64.const 100)) (i64.const 100)) 244 | (assert_return (invoke "i64_load8_u" (i64.const 200)) (i64.const 200)) 245 | (assert_return (invoke "i64_load16_s" (i64.const 20000)) (i64.const 20000)) 246 | (assert_return (invoke "i64_load16_u" (i64.const 40000)) (i64.const 40000)) 247 | (assert_return (invoke "i64_load32_s" (i64.const 20000)) (i64.const 20000)) 248 | (assert_return (invoke "i64_load32_u" (i64.const 40000)) (i64.const 40000)) 249 | -------------------------------------------------------------------------------- /test/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 | (export "zero_everything" $zero_everything) 9 | (func $zero_everything 10 | (i32.store (i32.const 0) (i32.const 0)) 11 | (i32.store (i32.const 4) (i32.const 0)) 12 | (i32.store (i32.const 8) (i32.const 0)) 13 | (i32.store (i32.const 12) (i32.const 0)) 14 | ) 15 | 16 | (export "test_store_to_load" $test_store_to_load) 17 | (func $test_store_to_load (result i32) 18 | (i32.store (i32.const 8) (i32.const 0)) 19 | (f32.store (i32.const 5) (f32.const -0.0)) 20 | (i32.load (i32.const 8)) 21 | ) 22 | 23 | (export "test_redundant_load" $test_redundant_load) 24 | (func $test_redundant_load (result i32) 25 | (i32.load (i32.const 8)) 26 | (f32.store (i32.const 5) (f32.const -0.0)) 27 | (i32.load (i32.const 8)) 28 | ) 29 | 30 | (export "test_dead_store" $test_dead_store) 31 | (func $test_dead_store (result f32) 32 | (local $t f32) 33 | (i32.store (i32.const 8) (i32.const 0x23232323)) 34 | (set_local $t (f32.load (i32.const 11))) 35 | (i32.store (i32.const 8) (i32.const 0)) 36 | (get_local $t) 37 | ) 38 | ) 39 | 40 | (assert_return (invoke "test_store_to_load") (i32.const 0x00000080)) 41 | (invoke "zero_everything") 42 | (assert_return (invoke "test_redundant_load") (i32.const 0x00000080)) 43 | (invoke "zero_everything") 44 | (assert_return (invoke "test_dead_store") (f32.const 0x1.18p-144)) 45 | -------------------------------------------------------------------------------- /test/memory_trap.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (memory 1) 3 | 4 | (func $addr_limit (result i32) 5 | (i32.mul (current_memory) (i32.const 0x10000)) 6 | ) 7 | 8 | (export "store" $store) 9 | (func $store (param $i i32) (param $v i32) (result i32) 10 | (i32.store (i32.add (call $addr_limit) (get_local $i)) (get_local $v)) 11 | ) 12 | 13 | (export "load" $load) 14 | (func $load (param $i i32) (result i32) 15 | (i32.load (i32.add (call $addr_limit) (get_local $i))) 16 | ) 17 | 18 | (export "grow_memory" $grow_memory) 19 | (func $grow_memory (param i32) 20 | (grow_memory (get_local 0)) 21 | ) 22 | ) 23 | 24 | (assert_return (invoke "store" (i32.const -4) (i32.const 42)) (i32.const 42)) 25 | (assert_return (invoke "load" (i32.const -4)) (i32.const 42)) 26 | (assert_trap (invoke "store" (i32.const -3) (i32.const 13)) "out of bounds memory access") 27 | (assert_trap (invoke "load" (i32.const -3)) "out of bounds memory access") 28 | (assert_trap (invoke "store" (i32.const -2) (i32.const 13)) "out of bounds memory access") 29 | (assert_trap (invoke "load" (i32.const -2)) "out of bounds memory access") 30 | (assert_trap (invoke "store" (i32.const -1) (i32.const 13)) "out of bounds memory access") 31 | (assert_trap (invoke "load" (i32.const -1)) "out of bounds memory access") 32 | (assert_trap (invoke "store" (i32.const 0) (i32.const 13)) "out of bounds memory access") 33 | (assert_trap (invoke "load" (i32.const 0)) "out of bounds memory access") 34 | (assert_trap (invoke "store" (i32.const 0x80000000) (i32.const 13)) "out of bounds memory access") 35 | (assert_trap (invoke "load" (i32.const 0x80000000)) "out of bounds memory access") 36 | (assert_trap (invoke "grow_memory" (i32.const 0x80000000)) "memory size exceeds implementation limit") 37 | -------------------------------------------------------------------------------- /test/names.wast: -------------------------------------------------------------------------------- 1 | ;; Test files can define multiple modules. Test that implementations treat 2 | ;; each module independently from the other. 3 | 4 | (module 5 | (func $foo (result i32) (i32.const 0)) 6 | (export "foo" $foo) 7 | ) 8 | 9 | (assert_return (invoke "foo") (i32.const 0)) 10 | 11 | ;; Another module, same function name, different contents. 12 | 13 | (module 14 | (func $foo (result i32) (i32.const 1)) 15 | (export "foo" $foo) 16 | ) 17 | 18 | (assert_return (invoke "foo") (i32.const 1)) 19 | 20 | 21 | (module 22 | ;; Test that we can use the empty string as a symbol. 23 | (func (result f32) (f32.const 0x1.91p+2)) 24 | (export "" 0) 25 | 26 | ;; Test that we can use common libc names without conflict. 27 | (func $malloc (result f32) (f32.const 0x1.92p+2)) 28 | (export "malloc" $malloc) 29 | 30 | ;; Test that we can use some libc hidden names without conflict. 31 | (func $_malloc (result f32) (f32.const 0x1.93p+2)) 32 | (func $__malloc (result f32) (f32.const 0x1.94p+2)) 33 | (func (result f32) (f32.const 0x1.95p+2)) 34 | (export "_malloc" $_malloc) 35 | (export "__malloc" $__malloc) 36 | 37 | ;; Test that we can use non-alphanumeric names. 38 | (func (result f32) (f32.const 0x1.96p+2)) 39 | (export "~!@#$%^&*()_+`-={}|[]\\:\";'<>?,./ " 5) 40 | 41 | ;; Test that we can use names beginning with a digit. 42 | (func (result f32) (f32.const 0x1.97p+2)) 43 | (export "0" 6) 44 | 45 | ;; Test that we can use names beginning with an underscore. 46 | (func $_ (result f32) (f32.const 0x1.98p+2)) 47 | (export "_" $_) 48 | 49 | ;; Test that we can use names beginning with a dollar sign. 50 | (func (result f32) (f32.const 0x1.99p+2)) 51 | (export "$" 8) 52 | 53 | ;; Test that we can use names beginning with an at sign. 54 | (func (result f32) (f32.const 0x2.00p+2)) 55 | (export "@" 9) 56 | 57 | ;; Test that we can use names that have special meaning in JS. 58 | (func $NaN (result f32) (f32.const 0x2.01p+2)) 59 | (func $Infinity (result f32) (f32.const 0x2.02p+2)) 60 | (func $if (result f32) (f32.const 0x2.03p+2)) 61 | (export "NaN" $NaN) 62 | (export "Infinity" $Infinity) 63 | (export "if" $if) 64 | ) 65 | 66 | (assert_return (invoke "") (f32.const 0x1.91p+2)) 67 | (assert_return (invoke "malloc") (f32.const 0x1.92p+2)) 68 | (assert_return (invoke "_malloc") (f32.const 0x1.93p+2)) 69 | (assert_return (invoke "__malloc") (f32.const 0x1.94p+2)) 70 | (assert_return (invoke "~!@#$%^&*()_+`-={}|[]\\:\";'<>?,./ ") (f32.const 0x1.96p+2)) 71 | (assert_return (invoke "0") (f32.const 0x1.97p+2)) 72 | (assert_return (invoke "_") (f32.const 0x1.98p+2)) 73 | (assert_return (invoke "$") (f32.const 0x1.99p+2)) 74 | (assert_return (invoke "@") (f32.const 0x2.00p+2)) 75 | (assert_return (invoke "NaN") (f32.const 0x2.01p+2)) 76 | (assert_return (invoke "Infinity") (f32.const 0x2.02p+2)) 77 | (assert_return (invoke "if") (f32.const 0x2.03p+2)) 78 | 79 | (module 80 | ;; Test that we can use indices instead of names to reference imports, 81 | ;; functions and parameters. 82 | (import "spectest" "print" (param i32)) 83 | (import "spectest" "print" (param i32)) 84 | (func (param i32) (param i32) 85 | (call_import 0 (get_local 0)) 86 | (call_import 1 (get_local 1)) 87 | ) 88 | (export "print32" 0) 89 | ) 90 | 91 | (invoke "print32" (i32.const 42) (i32.const 123)) 92 | -------------------------------------------------------------------------------- /test/nop.wast: -------------------------------------------------------------------------------- 1 | ;; Test `nop` operator. 2 | 3 | (module 4 | (func $dummy) 5 | 6 | (func "as-func-first" (result i32) 7 | (nop) (i32.const 1) 8 | ) 9 | (func "as-func-mid" (result i32) 10 | (call $dummy) (nop) (i32.const 2) 11 | ) 12 | (func "as-func-last" 13 | (call $dummy) (nop) 14 | ) 15 | 16 | (func "as-block-first" (result i32) 17 | (block (nop) (i32.const 2)) 18 | ) 19 | (func "as-block-mid" (result i32) 20 | (block (call $dummy) (nop) (i32.const 2)) 21 | ) 22 | (func "as-block-last" 23 | (block (nop) (call $dummy) (nop)) 24 | ) 25 | 26 | (func "as-loop-first" (result i32) 27 | (loop (nop) (i32.const 2)) 28 | ) 29 | (func "as-loop-mid" (result i32) 30 | (loop (call $dummy) (nop) (i32.const 2)) 31 | ) 32 | (func "as-loop-last" 33 | (loop (call $dummy) (nop)) 34 | ) 35 | 36 | (func "as-br-value" 37 | (block (br 0 (nop))) 38 | ) 39 | (func "as-br_if-value" (param i32) 40 | (block (br_if 0 (nop) (get_local 0))) 41 | ) 42 | (func "as-br_table-value" (param i32) 43 | (block (br_table 0 0 0 (nop) (get_local 0))) 44 | ) 45 | 46 | (func "as-return-value" 47 | (block (return (nop))) 48 | ) 49 | 50 | (func "as-if-then" (param i32) 51 | (block (if (get_local 0) (nop) (call $dummy))) 52 | ) 53 | (func "as-if-else" (param i32) 54 | (block (if (get_local 0) (call $dummy) (nop))) 55 | ) 56 | ) 57 | 58 | (assert_return (invoke "as-func-first") (i32.const 1)) 59 | (assert_return (invoke "as-func-mid") (i32.const 2)) 60 | (assert_return (invoke "as-func-last")) 61 | 62 | (assert_return (invoke "as-block-first") (i32.const 2)) 63 | (assert_return (invoke "as-block-mid") (i32.const 2)) 64 | (assert_return (invoke "as-block-last")) 65 | 66 | (assert_return (invoke "as-loop-first") (i32.const 2)) 67 | (assert_return (invoke "as-loop-mid") (i32.const 2)) 68 | (assert_return (invoke "as-loop-last")) 69 | 70 | (assert_return (invoke "as-br-value")) 71 | 72 | (assert_return (invoke "as-br_if-value" (i32.const 0))) 73 | (assert_return (invoke "as-br_if-value" (i32.const 10))) 74 | 75 | (assert_return (invoke "as-br_table-value" (i32.const 0))) 76 | (assert_return (invoke "as-br_table-value" (i32.const 1))) 77 | (assert_return (invoke "as-br_table-value" (i32.const 10))) 78 | 79 | (assert_return (invoke "as-return-value")) 80 | 81 | (assert_return (invoke "as-if-then" (i32.const 0))) 82 | (assert_return (invoke "as-if-then" (i32.const 4))) 83 | (assert_return (invoke "as-if-else" (i32.const 0))) 84 | (assert_return (invoke "as-if-else" (i32.const 3))) 85 | 86 | (assert_invalid 87 | (module (func $type-i32 (result i32) (nop))) 88 | "type mismatch" 89 | ) 90 | (assert_invalid 91 | (module (func $type-i64 (result i64) (nop))) 92 | "type mismatch" 93 | ) 94 | (assert_invalid 95 | (module (func $type-f32 (result f32) (nop))) 96 | "type mismatch" 97 | ) 98 | (assert_invalid 99 | (module (func $type-f64 (result f64) (nop))) 100 | "type mismatch" 101 | ) 102 | -------------------------------------------------------------------------------- /test/resizing.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (memory 0) 3 | 4 | (export "load_at_zero" $load_at_zero) 5 | (func $load_at_zero (result i32) (i32.load (i32.const 0))) 6 | 7 | (export "store_at_zero" $store_at_zero) 8 | (func $store_at_zero (result i32) (i32.store (i32.const 0) (i32.const 2))) 9 | 10 | (export "load_at_page_size" $load_at_page_size) 11 | (func $load_at_page_size (result i32) (i32.load (i32.const 0x10000))) 12 | 13 | (export "store_at_page_size" $store_at_page_size) 14 | (func $store_at_page_size (result i32) (i32.store (i32.const 0x10000) (i32.const 3))) 15 | 16 | (export "grow" $grow) 17 | (func $grow (param $sz i32) (result i32) (grow_memory (get_local $sz))) 18 | 19 | (export "size" $size) 20 | (func $size (result i32) (current_memory)) 21 | ) 22 | 23 | (assert_return (invoke "size") (i32.const 0)) 24 | (assert_trap (invoke "store_at_zero") "out of bounds memory access") 25 | (assert_trap (invoke "load_at_zero") "out of bounds memory access") 26 | (assert_trap (invoke "store_at_page_size") "out of bounds memory access") 27 | (assert_trap (invoke "load_at_page_size") "out of bounds memory access") 28 | (assert_return (invoke "grow" (i32.const 1)) (i32.const 0)) 29 | (assert_return (invoke "size") (i32.const 1)) 30 | (assert_return (invoke "load_at_zero") (i32.const 0)) 31 | (assert_return (invoke "store_at_zero") (i32.const 2)) 32 | (assert_return (invoke "load_at_zero") (i32.const 2)) 33 | (assert_trap (invoke "store_at_page_size") "out of bounds memory access") 34 | (assert_trap (invoke "load_at_page_size") "out of bounds memory access") 35 | (assert_return (invoke "grow" (i32.const 4)) (i32.const 1)) 36 | (assert_return (invoke "size") (i32.const 5)) 37 | (assert_return (invoke "load_at_zero") (i32.const 2)) 38 | (assert_return (invoke "store_at_zero") (i32.const 2)) 39 | (assert_return (invoke "load_at_page_size") (i32.const 0)) 40 | (assert_return (invoke "store_at_page_size") (i32.const 3)) 41 | (assert_return (invoke "load_at_page_size") (i32.const 3)) 42 | -------------------------------------------------------------------------------- /test/return.wast: -------------------------------------------------------------------------------- 1 | ;; Test `return` operator 2 | 3 | (module 4 | (func "type-i32" (i32.ctz (return))) 5 | (func "type-i64" (i64.ctz (return))) 6 | (func "type-f32" (f32.neg (return))) 7 | (func "type-f64" (f64.neg (return))) 8 | 9 | (func "nullary" (return)) 10 | (func "unary" (result f64) (return (f64.const 3.1))) 11 | 12 | (func "as-func-first" (result i32) 13 | (return (i32.const 1)) (i32.const 2) 14 | ) 15 | (func "as-func-mid" (result i32) 16 | (i32.const 1) (return (i32.const 2)) (i32.const 3) 17 | ) 18 | (func "as-func-last" 19 | (nop) (i32.const 1) (return) 20 | ) 21 | (func "as-func-value" (result i32) 22 | (nop) (i32.const 1) (return (i32.const 3)) 23 | ) 24 | 25 | (func "as-block-first" 26 | (block (return) (i32.const 2)) 27 | ) 28 | (func "as-block-mid" 29 | (block (i32.const 1) (return) (i32.const 2)) 30 | ) 31 | (func "as-block-last" 32 | (block (nop) (i32.const 1) (return)) 33 | ) 34 | (func "as-block-value" (result i32) 35 | (block (nop) (i32.const 1) (return (i32.const 2))) 36 | ) 37 | 38 | (func "as-loop-first" (result i32) 39 | (loop (return (i32.const 3)) (i32.const 2)) 40 | ) 41 | (func "as-loop-mid" (result i32) 42 | (loop (i32.const 1) (return (i32.const 4)) (i32.const 2)) 43 | ) 44 | (func "as-loop-last" (result i32) 45 | (loop (nop) (i32.const 1) (return (i32.const 5))) 46 | ) 47 | 48 | (func "as-br-value" (result i32) 49 | (block (br 0 (return (i32.const 9)))) 50 | ) 51 | 52 | (func "as-br_if-cond" 53 | (block (br_if 0 (return))) 54 | ) 55 | (func "as-br_if-value" (result i32) 56 | (block (br_if 0 (return (i32.const 8)) (i32.const 1)) (i32.const 7)) 57 | ) 58 | (func "as-br_if-value-cond" (result i32) 59 | (block (br_if 0 (i32.const 6) (return (i32.const 9))) (i32.const 7)) 60 | ) 61 | 62 | (func "as-br_table-index" (result i64) 63 | (block (br_table 0 0 0 (return (i64.const 9)))) (i64.const -1) 64 | ) 65 | (func "as-br_table-value" (result i32) 66 | (block (br_table 0 0 0 (return (i32.const 10)) (i32.const 1)) (i32.const 7)) 67 | ) 68 | (func "as-br_table-value-index" (result i32) 69 | (block (br_table 0 0 (i32.const 6) (return (i32.const 11))) (i32.const 7)) 70 | ) 71 | 72 | (func "as-return-value" (result i64) 73 | (return (return (i64.const 7))) 74 | ) 75 | 76 | (func "as-if-cond" (result i32) 77 | (if (return (i32.const 2)) (i32.const 0) (i32.const 1)) 78 | ) 79 | (func "as-if-then" (param i32 i32) (result i32) 80 | (if (get_local 0) (return (i32.const 3)) (get_local 1)) 81 | ) 82 | (func "as-if-else" (param i32 i32) (result i32) 83 | (if (get_local 0) (get_local 1) (return (i32.const 4))) 84 | ) 85 | 86 | (func "as-select-first" (param i32 i32) (result i32) 87 | (select (return (i32.const 5)) (get_local 0) (get_local 1)) 88 | ) 89 | (func "as-select-second" (param i32 i32) (result i32) 90 | (select (get_local 0) (return (i32.const 6)) (get_local 1)) 91 | ) 92 | (func "as-select-cond" (result i32) 93 | (select (i32.const 0) (i32.const 1) (return (i32.const 7))) 94 | ) 95 | 96 | (func $f (param i32 i32 i32) (result i32) (i32.const -1)) 97 | (func "as-call-first" (result i32) 98 | (call $f (return (i32.const 12)) (i32.const 2) (i32.const 3)) 99 | ) 100 | (func "as-call-mid" (result i32) 101 | (call $f (i32.const 1) (return (i32.const 13)) (i32.const 3)) 102 | ) 103 | (func "as-call-last" (result i32) 104 | (call $f (i32.const 1) (i32.const 2) (return (i32.const 14))) 105 | ) 106 | 107 | (import "spectest" "print" (param i32 i32 i32)) 108 | (func "as-call_import-first" 109 | (call_import 0 (return) (i32.const 2) (i32.const 3)) 110 | ) 111 | (func "as-call_import-mid" 112 | (call_import 0 (i32.const 1) (return) (i32.const 3)) 113 | ) 114 | (func "as-call_import-last" 115 | (call_import 0 (i32.const 1) (i32.const 2) (return)) 116 | ) 117 | 118 | (type $sig (func (param i32 i32 i32) (result i32))) 119 | (table $f) 120 | (func "as-call_indirect-func" (result i32) 121 | (call_indirect $sig (return (i32.const 20)) (i32.const 1) (i32.const 2) (i32.const 3)) 122 | ) 123 | (func "as-call_indirect-first" (result i32) 124 | (call_indirect $sig (i32.const 0) (return (i32.const 21)) (i32.const 2) (i32.const 3)) 125 | ) 126 | (func "as-call_indirect-mid" (result i32) 127 | (call_indirect $sig (i32.const 0) (i32.const 1) (return (i32.const 22)) (i32.const 3)) 128 | ) 129 | (func "as-call_indirect-last" (result i32) 130 | (call_indirect $sig (i32.const 0) (i32.const 1) (i32.const 2) (return (i32.const 23))) 131 | ) 132 | 133 | (func "as-set_local-value" (result i32) (local f32) 134 | (set_local 0 (return (i32.const 17))) (i32.const -1) 135 | ) 136 | 137 | (memory 1) 138 | (func "as-load-address" (result f32) 139 | (f32.load (return (f32.const 1.7))) 140 | ) 141 | (func "as-loadN-address" (result i64) 142 | (i64.load8_s (return (i64.const 30))) 143 | ) 144 | 145 | (func "as-store-address" (result i32) 146 | (f64.store (return (i32.const 30)) (f64.const 7)) (i32.const -1) 147 | ) 148 | (func "as-store-value" (result i32) 149 | (i64.store (i32.const 2) (return (i32.const 31))) (i32.const -1) 150 | ) 151 | 152 | (func "as-storeN-address" (result i32) 153 | (i32.store8 (return (i32.const 32)) (i32.const 7)) (i32.const -1) 154 | ) 155 | (func "as-storeN-value" (result i32) 156 | (i64.store16 (i32.const 2) (return (i32.const 33))) (i32.const -1) 157 | ) 158 | 159 | (func "as-unary-operand" (result f32) 160 | (f32.neg (return (f32.const 3.4))) 161 | ) 162 | 163 | (func "as-binary-left" (result i32) 164 | (i32.add (return (i32.const 3)) (i32.const 10)) 165 | ) 166 | (func "as-binary-right" (result i64) 167 | (i64.sub (i64.const 10) (return (i64.const 45))) 168 | ) 169 | 170 | (func "as-test-operand" (result i32) 171 | (i32.eqz (return (i32.const 44))) 172 | ) 173 | 174 | (func "as-compare-left" (result i32) 175 | (f64.le (return (i32.const 43)) (f64.const 10)) 176 | ) 177 | (func "as-compare-right" (result i32) 178 | (f32.ne (f32.const 10) (return (i32.const 42))) 179 | ) 180 | 181 | (func "as-convert-operand" (result i32) 182 | (i32.wrap/i64 (return (i32.const 41))) 183 | ) 184 | 185 | (func "as-grow_memory-size" (result i32) 186 | (grow_memory (return (i32.const 40))) 187 | ) 188 | ) 189 | 190 | (assert_return (invoke "type-i32")) 191 | (assert_return (invoke "type-i64")) 192 | (assert_return (invoke "type-f32")) 193 | (assert_return (invoke "type-f64")) 194 | 195 | (assert_return (invoke "nullary")) 196 | (assert_return (invoke "unary") (f64.const 3.1)) 197 | 198 | (assert_return (invoke "as-func-first") (i32.const 1)) 199 | (assert_return (invoke "as-func-mid") (i32.const 2)) 200 | (assert_return (invoke "as-func-last")) 201 | (assert_return (invoke "as-func-value") (i32.const 3)) 202 | 203 | (assert_return (invoke "as-block-first")) 204 | (assert_return (invoke "as-block-mid")) 205 | (assert_return (invoke "as-block-last")) 206 | (assert_return (invoke "as-block-value") (i32.const 2)) 207 | 208 | (assert_return (invoke "as-loop-first") (i32.const 3)) 209 | (assert_return (invoke "as-loop-mid") (i32.const 4)) 210 | (assert_return (invoke "as-loop-last") (i32.const 5)) 211 | 212 | (assert_return (invoke "as-br-value") (i32.const 9)) 213 | 214 | (assert_return (invoke "as-br_if-cond")) 215 | (assert_return (invoke "as-br_if-value") (i32.const 8)) 216 | (assert_return (invoke "as-br_if-value-cond") (i32.const 9)) 217 | 218 | (assert_return (invoke "as-br_table-index") (i64.const 9)) 219 | (assert_return (invoke "as-br_table-value") (i32.const 10)) 220 | (assert_return (invoke "as-br_table-value-index") (i32.const 11)) 221 | 222 | (assert_return (invoke "as-return-value") (i64.const 7)) 223 | 224 | (assert_return (invoke "as-if-cond") (i32.const 2)) 225 | (assert_return (invoke "as-if-then" (i32.const 1) (i32.const 6)) (i32.const 3)) 226 | (assert_return (invoke "as-if-then" (i32.const 0) (i32.const 6)) (i32.const 6)) 227 | (assert_return (invoke "as-if-else" (i32.const 0) (i32.const 6)) (i32.const 4)) 228 | (assert_return (invoke "as-if-else" (i32.const 1) (i32.const 6)) (i32.const 6)) 229 | 230 | (assert_return (invoke "as-select-first" (i32.const 0) (i32.const 6)) (i32.const 5)) 231 | (assert_return (invoke "as-select-first" (i32.const 1) (i32.const 6)) (i32.const 5)) 232 | (assert_return (invoke "as-select-second" (i32.const 0) (i32.const 6)) (i32.const 6)) 233 | (assert_return (invoke "as-select-second" (i32.const 1) (i32.const 6)) (i32.const 6)) 234 | (assert_return (invoke "as-select-cond") (i32.const 7)) 235 | 236 | (assert_return (invoke "as-call-first") (i32.const 12)) 237 | (assert_return (invoke "as-call-mid") (i32.const 13)) 238 | (assert_return (invoke "as-call-last") (i32.const 14)) 239 | 240 | (assert_return (invoke "as-call_import-first")) 241 | (assert_return (invoke "as-call_import-mid")) 242 | (assert_return (invoke "as-call_import-last")) 243 | 244 | (assert_return (invoke "as-call_indirect-func") (i32.const 20)) 245 | (assert_return (invoke "as-call_indirect-first") (i32.const 21)) 246 | (assert_return (invoke "as-call_indirect-mid") (i32.const 22)) 247 | (assert_return (invoke "as-call_indirect-last") (i32.const 23)) 248 | 249 | (assert_return (invoke "as-set_local-value") (i32.const 17)) 250 | 251 | (assert_return (invoke "as-load-address") (f32.const 1.7)) 252 | (assert_return (invoke "as-loadN-address") (i64.const 30)) 253 | 254 | (assert_return (invoke "as-store-address") (i32.const 30)) 255 | (assert_return (invoke "as-store-value") (i32.const 31)) 256 | (assert_return (invoke "as-storeN-address") (i32.const 32)) 257 | (assert_return (invoke "as-storeN-value") (i32.const 33)) 258 | 259 | (assert_return (invoke "as-unary-operand") (f32.const 3.4)) 260 | 261 | (assert_return (invoke "as-binary-left") (i32.const 3)) 262 | (assert_return (invoke "as-binary-right") (i64.const 45)) 263 | 264 | (assert_return (invoke "as-test-operand") (i32.const 44)) 265 | 266 | (assert_return (invoke "as-compare-left") (i32.const 43)) 267 | (assert_return (invoke "as-compare-right") (i32.const 42)) 268 | 269 | (assert_return (invoke "as-convert-operand") (i32.const 41)) 270 | 271 | (assert_return (invoke "as-grow_memory-size") (i32.const 40)) 272 | 273 | (assert_invalid 274 | (module (func $type-value-void-vs-num (result f64) (return))) 275 | "type mismatch" 276 | ) 277 | (assert_invalid 278 | (module (func $type-value-num-vs-num (result f64) (return (i64.const 1)))) 279 | "type mismatch" 280 | ) 281 | 282 | -------------------------------------------------------------------------------- /test/select.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func $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 $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 $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 $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 $select_trap_l (param $cond i32) (result i32) 16 | (select (unreachable) (i32.const 0) (get_local $cond))) 17 | (func $select_trap_r (param $cond i32) (result i32) 18 | (select (i32.const 0) (unreachable) (get_local $cond))) 19 | 20 | (export "select_i32" $select_i32) 21 | (export "select_i64" $select_i64) 22 | (export "select_f32" $select_f32) 23 | (export "select_f64" $select_f64) 24 | (export "select_trap_l" $select_trap_l) 25 | (export "select_trap_r" $select_trap_r) 26 | ) 27 | 28 | (assert_return (invoke "select_i32" (i32.const 1) (i32.const 2) (i32.const 1)) (i32.const 1)) 29 | (assert_return (invoke "select_i64" (i64.const 2) (i64.const 1) (i32.const 1)) (i64.const 2)) 30 | (assert_return (invoke "select_f32" (f32.const 1) (f32.const 2) (i32.const 1)) (f32.const 1)) 31 | (assert_return (invoke "select_f64" (f64.const 1) (f64.const 2) (i32.const 1)) (f64.const 1)) 32 | 33 | (assert_return (invoke "select_i32" (i32.const 1) (i32.const 2) (i32.const 0)) (i32.const 2)) 34 | (assert_return (invoke "select_i32" (i32.const 2) (i32.const 1) (i32.const 0)) (i32.const 1)) 35 | (assert_return (invoke "select_i64" (i64.const 2) (i64.const 1) (i32.const -1)) (i64.const 2)) 36 | (assert_return (invoke "select_i64" (i64.const 2) (i64.const 1) (i32.const 0xf0f0f0f0)) (i64.const 2)) 37 | 38 | (assert_return (invoke "select_f32" (f32.const nan) (f32.const 1) (i32.const 1)) (f32.const nan)) 39 | (assert_return (invoke "select_f32" (f32.const nan:0x20304) (f32.const 1) (i32.const 1)) (f32.const nan:0x20304)) 40 | (assert_return (invoke "select_f32" (f32.const nan) (f32.const 1) (i32.const 0)) (f32.const 1)) 41 | (assert_return (invoke "select_f32" (f32.const nan:0x20304) (f32.const 1) (i32.const 0)) (f32.const 1)) 42 | (assert_return (invoke "select_f32" (f32.const 2) (f32.const nan) (i32.const 1)) (f32.const 2)) 43 | (assert_return (invoke "select_f32" (f32.const 2) (f32.const nan:0x20304) (i32.const 1)) (f32.const 2)) 44 | (assert_return (invoke "select_f32" (f32.const 2) (f32.const nan) (i32.const 0)) (f32.const nan)) 45 | (assert_return (invoke "select_f32" (f32.const 2) (f32.const nan:0x20304) (i32.const 0)) (f32.const nan:0x20304)) 46 | 47 | (assert_return (invoke "select_f64" (f64.const nan) (f64.const 1) (i32.const 1)) (f64.const nan)) 48 | (assert_return (invoke "select_f64" (f64.const nan:0x20304) (f64.const 1) (i32.const 1)) (f64.const nan:0x20304)) 49 | (assert_return (invoke "select_f64" (f64.const nan) (f64.const 1) (i32.const 0)) (f64.const 1)) 50 | (assert_return (invoke "select_f64" (f64.const nan:0x20304) (f64.const 1) (i32.const 0)) (f64.const 1)) 51 | (assert_return (invoke "select_f64" (f64.const 2) (f64.const nan) (i32.const 1)) (f64.const 2)) 52 | (assert_return (invoke "select_f64" (f64.const 2) (f64.const nan:0x20304) (i32.const 1)) (f64.const 2)) 53 | (assert_return (invoke "select_f64" (f64.const 2) (f64.const nan) (i32.const 0)) (f64.const nan)) 54 | (assert_return (invoke "select_f64" (f64.const 2) (f64.const nan:0x20304) (i32.const 0)) (f64.const nan:0x20304)) 55 | 56 | (assert_trap (invoke "select_trap_l" (i32.const 1)) "unreachable executed") 57 | (assert_trap (invoke "select_trap_l" (i32.const 0)) "unreachable executed") 58 | (assert_trap (invoke "select_trap_r" (i32.const 1)) "unreachable executed") 59 | (assert_trap (invoke "select_trap_r" (i32.const 0)) "unreachable executed") 60 | -------------------------------------------------------------------------------- /test/set_local.wast: -------------------------------------------------------------------------------- 1 | ;; Test `set_local` operator 2 | 3 | (module 4 | ;; Typing 5 | 6 | (func "type-local-i32" (result i32) (local i32) (set_local 0 (i32.const 0))) 7 | (func "type-local-i64" (result i64) (local i64) (set_local 0 (i64.const 0))) 8 | (func "type-local-f32" (result f32) (local f32) (set_local 0 (f32.const 0))) 9 | (func "type-local-f64" (result f64) (local f64) (set_local 0 (f64.const 0))) 10 | 11 | (func "type-param-i32" (param i32) (result i32) (set_local 0 (i32.const 10))) 12 | (func "type-param-i64" (param i64) (result i64) (set_local 0 (i64.const 11))) 13 | (func "type-param-f32" (param f32) (result f32) (set_local 0 (f32.const 11.1))) 14 | (func "type-param-f64" (param f64) (result f64) (set_local 0 (f64.const 12.2))) 15 | 16 | (func "type-mixed" (param i64 f32 f64 i32 i32) (local f32 i64 i64 f64) 17 | (i64.eqz (set_local 0 (i64.const 0))) 18 | (f32.neg (set_local 1 (f32.const 0))) 19 | (f64.neg (set_local 2 (f64.const 0))) 20 | (i32.eqz (set_local 3 (i32.const 0))) 21 | (i32.eqz (set_local 4 (i32.const 0))) 22 | (f32.neg (set_local 5 (f32.const 0))) 23 | (i64.eqz (set_local 6 (i64.const 0))) 24 | (i64.eqz (set_local 7 (i64.const 0))) 25 | (f64.neg (set_local 8 (f64.const 0))) 26 | ) 27 | 28 | ;; Writing 29 | 30 | (func "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 | ;; Result 68 | 69 | (func "result" (param i64 f32 f64 i32 i32) (result f64) 70 | (local f32 i64 i64 f64) 71 | (f64.add 72 | (f64.convert_u/i64 (set_local 0 (i64.const 1))) 73 | (f64.add 74 | (f64.promote/f32 (set_local 1 (f32.const 2))) 75 | (f64.add 76 | (set_local 2 (f64.const 3.3)) 77 | (f64.add 78 | (f64.convert_u/i32 (set_local 3 (i32.const 4))) 79 | (f64.add 80 | (f64.convert_s/i32 (set_local 4 (i32.const 5))) 81 | (f64.add 82 | (f64.promote/f32 (set_local 5 (f32.const 5.5))) 83 | (f64.add 84 | (f64.convert_u/i64 (set_local 6 (i64.const 6))) 85 | (f64.add 86 | (f64.convert_u/i64 (set_local 7 (i64.const 0))) 87 | (set_local 8 (f64.const 8)) 88 | ) 89 | ) 90 | ) 91 | ) 92 | ) 93 | ) 94 | ) 95 | ) 96 | ) 97 | ) 98 | 99 | (assert_return (invoke "type-local-i32") (i32.const 0)) 100 | (assert_return (invoke "type-local-i64") (i64.const 0)) 101 | (assert_return (invoke "type-local-f32") (f32.const 0)) 102 | (assert_return (invoke "type-local-f64") (f64.const 0)) 103 | 104 | (assert_return (invoke "type-param-i32" (i32.const 2)) (i32.const 10)) 105 | (assert_return (invoke "type-param-i64" (i64.const 3)) (i64.const 11)) 106 | (assert_return (invoke "type-param-f32" (f32.const 4.4)) (f32.const 11.1)) 107 | (assert_return (invoke "type-param-f64" (f64.const 5.5)) (f64.const 12.2)) 108 | 109 | (assert_return 110 | (invoke "type-mixed" 111 | (i64.const 1) (f32.const 2.2) (f64.const 3.3) (i32.const 4) (i32.const 5) 112 | ) 113 | ) 114 | 115 | (assert_return 116 | (invoke "write" 117 | (i64.const 1) (f32.const 2) (f64.const 3.3) (i32.const 4) (i32.const 5) 118 | ) 119 | (i64.const 56) 120 | ) 121 | 122 | (assert_return 123 | (invoke "result" 124 | (i64.const -1) (f32.const -2) (f64.const -3.3) (i32.const -4) (i32.const -5) 125 | ) 126 | (f64.const 34.8) 127 | ) 128 | 129 | 130 | ;; Invalid typing of access to locals 131 | 132 | (assert_invalid 133 | (module (func $type-local-num-vs-num (result i64) (local i32) (set_local 0 (i32.const 0)))) 134 | "type mismatch" 135 | ) 136 | (assert_invalid 137 | (module (func $type-local-num-vs-num (local f32) (i32.eqz (set_local 0 (f32.const 0))))) 138 | "type mismatch" 139 | ) 140 | (assert_invalid 141 | (module (func $type-local-num-vs-num (local f64 i64) (f64.neg (set_local 1 (i64.const 0))))) 142 | "type mismatch" 143 | ) 144 | 145 | (assert_invalid 146 | (module (func $type-local-arg-void-vs-num (local i32) (set_local 0 (nop)))) 147 | "type mismatch" 148 | ) 149 | (assert_invalid 150 | (module (func $type-local-arg-num-vs-num (local i32) (set_local 0 (f32.const 0)))) 151 | "type mismatch" 152 | ) 153 | (assert_invalid 154 | (module (func $type-local-arg-num-vs-num (local f32) (set_local 0 (f64.const 0)))) 155 | "type mismatch" 156 | ) 157 | (assert_invalid 158 | (module (func $type-local-arg-num-vs-num (local f64 i64) (set_local 1 (f64.const 0)))) 159 | "type mismatch" 160 | ) 161 | 162 | 163 | ;; Invalid typing of access to parameters 164 | 165 | (assert_invalid 166 | (module (func $type-param-num-vs-num (param i32) (result i64) (get_local 0))) 167 | "type mismatch" 168 | ) 169 | (assert_invalid 170 | (module (func $type-param-num-vs-num (param f32) (i32.eqz (get_local 0)))) 171 | "type mismatch" 172 | ) 173 | (assert_invalid 174 | (module (func $type-param-num-vs-num (param f64 i64) (f64.neg (get_local 1)))) 175 | "type mismatch" 176 | ) 177 | 178 | (assert_invalid 179 | (module (func $type-param-arg-void-vs-num (param i32) (set_local 0 (nop)))) 180 | "type mismatch" 181 | ) 182 | (assert_invalid 183 | (module (func $type-param-arg-num-vs-num (param i32) (set_local 0 (f32.const 0)))) 184 | "type mismatch" 185 | ) 186 | (assert_invalid 187 | (module (func $type-param-arg-num-vs-num (param f32) (set_local 0 (f64.const 0)))) 188 | "type mismatch" 189 | ) 190 | (assert_invalid 191 | (module (func $type-param-arg-num-vs-num (param f64 i64) (set_local 1 (f64.const 0)))) 192 | "type mismatch" 193 | ) 194 | 195 | 196 | ;; Invalid local index 197 | 198 | (assert_invalid 199 | (module (func $unbound-local (local i32 i64) (get_local 3))) 200 | "unknown local" 201 | ) 202 | (assert_invalid 203 | (module (func $large-local (local i32 i64) (get_local 14324343))) 204 | "unknown local" 205 | ) 206 | 207 | (assert_invalid 208 | (module (func $unbound-param (param i32 i64) (get_local 2))) 209 | "unknown local" 210 | ) 211 | (assert_invalid 212 | (module (func $large-param (local i32 i64) (get_local 714324343))) 213 | "unknown local" 214 | ) 215 | 216 | (assert_invalid 217 | (module (func $unbound-mixed (param i32) (local i32 i64) (get_local 3))) 218 | "unknown local" 219 | ) 220 | (assert_invalid 221 | (module (func $large-mixed (param i64) (local i32 i64) (get_local 214324343))) 222 | "unknown local" 223 | ) 224 | 225 | (assert_invalid 226 | (module (func $type-mixed-arg-num-vs-num (param f32) (local i32) (set_local 1 (f32.const 0)))) 227 | "type mismatch" 228 | ) 229 | (assert_invalid 230 | (module (func $type-mixed-arg-num-vs-num (param i64 i32) (local f32) (set_local 1 (f32.const 0)))) 231 | "type mismatch" 232 | ) 233 | (assert_invalid 234 | (module (func $type-mixed-arg-num-vs-num (param i64) (local f64 i64) (set_local 1 (i64.const 0)))) 235 | "type mismatch" 236 | ) 237 | 238 | -------------------------------------------------------------------------------- /test/start.wast: -------------------------------------------------------------------------------- 1 | (assert_invalid 2 | (module (func (i32.const 1)) (start 1)) 3 | "unknown function 1" 4 | ) 5 | (assert_invalid 6 | (module 7 | (func $main (result i32) (return (i32.const 0))) 8 | (start $main) 9 | ) 10 | "start function must not return anything" 11 | ) 12 | (assert_invalid 13 | (module 14 | (func $main (param $a i32)) 15 | (start $main) 16 | ) 17 | "start function must be nullary" 18 | ) 19 | (module 20 | (memory 1 (segment 0 "A")) 21 | (func $inc 22 | (i32.store8 23 | (i32.const 0) 24 | (i32.add 25 | (i32.load8_u (i32.const 0)) 26 | (i32.const 1) 27 | ) 28 | ) 29 | ) 30 | (func $get (result i32) 31 | (return (i32.load8_u (i32.const 0))) 32 | ) 33 | (func $main 34 | (call $inc) 35 | (call $inc) 36 | (call $inc) 37 | ) 38 | (start $main) 39 | (export "inc" $inc) 40 | (export "get" $get) 41 | ) 42 | (assert_return (invoke "get") (i32.const 68)) 43 | (invoke "inc") 44 | (assert_return (invoke "get") (i32.const 69)) 45 | (invoke "inc") 46 | (assert_return (invoke "get") (i32.const 70)) 47 | 48 | (module 49 | (memory 1 (segment 0 "A")) 50 | (func $inc 51 | (i32.store8 52 | (i32.const 0) 53 | (i32.add 54 | (i32.load8_u (i32.const 0)) 55 | (i32.const 1) 56 | ) 57 | ) 58 | ) 59 | (func $get (result i32) 60 | (return (i32.load8_u (i32.const 0))) 61 | ) 62 | (func $main 63 | (call $inc) 64 | (call $inc) 65 | (call $inc) 66 | ) 67 | (start 2) 68 | (export "inc" $inc) 69 | (export "get" $get) 70 | ) 71 | (assert_return (invoke "get") (i32.const 68)) 72 | (invoke "inc") 73 | (assert_return (invoke "get") (i32.const 69)) 74 | (invoke "inc") 75 | (assert_return (invoke "get") (i32.const 70)) 76 | 77 | (module 78 | (import $print_i32 "spectest" "print" (param i32)) 79 | (func $main 80 | (call_import $print_i32 (i32.const 1))) 81 | (start 0) 82 | ) 83 | 84 | (module 85 | (import $print_i32 "spectest" "print" (param i32)) 86 | (func $main 87 | (call_import $print_i32 (i32.const 2))) 88 | (start $main) 89 | ) 90 | -------------------------------------------------------------------------------- /test/store_retval.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (memory 1) 3 | 4 | (import $print_i32 "spectest" "print" (param i32)) 5 | (import $print_i64 "spectest" "print" (param i64)) 6 | (import $print_f32 "spectest" "print" (param f32)) 7 | (import $print_f64 "spectest" "print" (param f64)) 8 | 9 | (func $run 10 | (local $i32 i32) (local $i64 i64) (local $f32 f32) (local $f64 f64) 11 | (call_import $print_i32 (set_local $i32 (i32.const 1))) 12 | (call_import $print_i64 (set_local $i64 (i64.const 2))) 13 | (call_import $print_f32 (set_local $f32 (f32.const 3))) 14 | (call_import $print_f64 (set_local $f64 (f64.const 4))) 15 | 16 | (call_import $print_i32 (i32.store (i32.const 0) (i32.const 11))) 17 | (call_import $print_i64 (i64.store (i32.const 0) (i64.const 12))) 18 | (call_import $print_f32 (f32.store (i32.const 0) (f32.const 13))) 19 | (call_import $print_f64 (f64.store (i32.const 0) (f64.const 14))) 20 | 21 | (call_import $print_i32 (i32.store8 (i32.const 0) (i32.const 512))) 22 | (call_import $print_i32 (i32.store16 (i32.const 0) (i32.const 65536))) 23 | (call_import $print_i64 (i64.store8 (i32.const 0) (i64.const 512))) 24 | (call_import $print_i64 (i64.store16 (i32.const 0) (i64.const 65536))) 25 | (call_import $print_i64 (i64.store32 (i32.const 0) (i64.const 4294967296))) 26 | ) 27 | (export "run" $run) 28 | ) 29 | 30 | (invoke "run") 31 | 32 | (assert_invalid 33 | (module (func (local $i32 i32) (local $i64 i64) 34 | (set_local $i64 (set_local $i32 (i32.const 1))))) 35 | "type mismatch: expression has type i32 but the context requires i64" 36 | ) 37 | (assert_invalid 38 | (module (func (local $i32 i32) (local $i64 i64) 39 | (set_local $i32 (set_local $i64 (i64.const 1))))) 40 | "type mismatch: expression has type i64 but the context requires i32" 41 | ) 42 | (assert_invalid 43 | (module (func (local $f32 f32) (local $f64 f64) 44 | (set_local $f64 (set_local $f32 (f32.const 1))))) 45 | "type mismatch: expression has type f32 but the context requires f64" 46 | ) 47 | (assert_invalid 48 | (module (func (local $f32 f32) (local $f64 f64) 49 | (set_local $f32 (set_local $f64 (f64.const 1))))) 50 | "type mismatch: expression has type f64 but the context requires f32" 51 | ) 52 | -------------------------------------------------------------------------------- /test/switch.wast: -------------------------------------------------------------------------------- 1 | (module 2 | ;; Statement switch 3 | (func $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 $expr (param $i i64) (result i64) 47 | (local $j i64) 48 | (set_local $j (i64.const 100)) 49 | (return 50 | (block $switch 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 $arg (param $i i32) (result i32) 89 | (return 90 | (block $2 91 | (i32.add (i32.const 10) 92 | (block $1 93 | (i32.add (i32.const 100) 94 | (block $0 95 | (i32.add (i32.const 1000) 96 | (block $default 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 $corner (result i32) 113 | (block 114 | (br_table 0 (i32.const 0)) 115 | ) 116 | (i32.const 1) 117 | ) 118 | 119 | (export "stmt" $stmt) 120 | (export "expr" $expr) 121 | (export "arg" $arg) 122 | (export "corner" $corner) 123 | ) 124 | 125 | (assert_return (invoke "stmt" (i32.const 0)) (i32.const 0)) 126 | (assert_return (invoke "stmt" (i32.const 1)) (i32.const -1)) 127 | (assert_return (invoke "stmt" (i32.const 2)) (i32.const -2)) 128 | (assert_return (invoke "stmt" (i32.const 3)) (i32.const -3)) 129 | (assert_return (invoke "stmt" (i32.const 4)) (i32.const 100)) 130 | (assert_return (invoke "stmt" (i32.const 5)) (i32.const 101)) 131 | (assert_return (invoke "stmt" (i32.const 6)) (i32.const 102)) 132 | (assert_return (invoke "stmt" (i32.const 7)) (i32.const 100)) 133 | (assert_return (invoke "stmt" (i32.const -10)) (i32.const 102)) 134 | 135 | (assert_return (invoke "expr" (i64.const 0)) (i64.const 0)) 136 | (assert_return (invoke "expr" (i64.const 1)) (i64.const -1)) 137 | (assert_return (invoke "expr" (i64.const 2)) (i64.const -2)) 138 | (assert_return (invoke "expr" (i64.const 3)) (i64.const -3)) 139 | (assert_return (invoke "expr" (i64.const 6)) (i64.const 101)) 140 | (assert_return (invoke "expr" (i64.const 7)) (i64.const -5)) 141 | (assert_return (invoke "expr" (i64.const -10)) (i64.const 100)) 142 | 143 | (assert_return (invoke "arg" (i32.const 0)) (i32.const 110)) 144 | (assert_return (invoke "arg" (i32.const 1)) (i32.const 12)) 145 | (assert_return (invoke "arg" (i32.const 2)) (i32.const 4)) 146 | (assert_return (invoke "arg" (i32.const 3)) (i32.const 1116)) 147 | (assert_return (invoke "arg" (i32.const 4)) (i32.const 118)) 148 | (assert_return (invoke "arg" (i32.const 5)) (i32.const 20)) 149 | (assert_return (invoke "arg" (i32.const 6)) (i32.const 12)) 150 | (assert_return (invoke "arg" (i32.const 7)) (i32.const 1124)) 151 | (assert_return (invoke "arg" (i32.const 8)) (i32.const 126)) 152 | 153 | (assert_return (invoke "corner") (i32.const 1)) 154 | 155 | (assert_invalid (module (func (br_table 3 (i32.const 0)))) "unknown label") 156 | -------------------------------------------------------------------------------- /test/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 $no_dce.i32.div_s (param $x i32) (param $y i32) 7 | (i32.div_s (get_local $x) (get_local $y))) 8 | (func $no_dce.i32.div_u (param $x i32) (param $y i32) 9 | (i32.div_u (get_local $x) (get_local $y))) 10 | (func $no_dce.i64.div_s (param $x i64) (param $y i64) 11 | (i64.div_s (get_local $x) (get_local $y))) 12 | (func $no_dce.i64.div_u (param $x i64) (param $y i64) 13 | (i64.div_u (get_local $x) (get_local $y))) 14 | (export "no_dce.i32.div_s" $no_dce.i32.div_s) 15 | (export "no_dce.i32.div_u" $no_dce.i32.div_u) 16 | (export "no_dce.i64.div_s" $no_dce.i64.div_s) 17 | (export "no_dce.i64.div_u" $no_dce.i64.div_u) 18 | ) 19 | 20 | (assert_trap (invoke "no_dce.i32.div_s" (i32.const 1) (i32.const 0)) "integer divide by zero") 21 | (assert_trap (invoke "no_dce.i32.div_u" (i32.const 1) (i32.const 0)) "integer divide by zero") 22 | (assert_trap (invoke "no_dce.i64.div_s" (i64.const 1) (i64.const 0)) "integer divide by zero") 23 | (assert_trap (invoke "no_dce.i64.div_u" (i64.const 1) (i64.const 0)) "integer divide by zero") 24 | 25 | (module 26 | (func $no_dce.i32.rem_s (param $x i32) (param $y i32) 27 | (i32.rem_s (get_local $x) (get_local $y))) 28 | (func $no_dce.i32.rem_u (param $x i32) (param $y i32) 29 | (i32.rem_u (get_local $x) (get_local $y))) 30 | (func $no_dce.i64.rem_s (param $x i64) (param $y i64) 31 | (i64.rem_s (get_local $x) (get_local $y))) 32 | (func $no_dce.i64.rem_u (param $x i64) (param $y i64) 33 | (i64.rem_u (get_local $x) (get_local $y))) 34 | (export "no_dce.i32.rem_s" $no_dce.i32.rem_s) 35 | (export "no_dce.i32.rem_u" $no_dce.i32.rem_u) 36 | (export "no_dce.i64.rem_s" $no_dce.i64.rem_s) 37 | (export "no_dce.i64.rem_u" $no_dce.i64.rem_u) 38 | ) 39 | 40 | (assert_trap (invoke "no_dce.i32.rem_s" (i32.const 1) (i32.const 0)) "integer divide by zero") 41 | (assert_trap (invoke "no_dce.i32.rem_u" (i32.const 1) (i32.const 0)) "integer divide by zero") 42 | (assert_trap (invoke "no_dce.i64.rem_s" (i64.const 1) (i64.const 0)) "integer divide by zero") 43 | (assert_trap (invoke "no_dce.i64.rem_u" (i64.const 1) (i64.const 0)) "integer divide by zero") 44 | 45 | (module 46 | (func $no_dce.i32.trunc_s_f32 (param $x f32) (i32.trunc_s/f32 (get_local $x))) 47 | (func $no_dce.i32.trunc_u_f32 (param $x f32) (i32.trunc_u/f32 (get_local $x))) 48 | (func $no_dce.i32.trunc_s_f64 (param $x f64) (i32.trunc_s/f64 (get_local $x))) 49 | (func $no_dce.i32.trunc_u_f64 (param $x f64) (i32.trunc_u/f64 (get_local $x))) 50 | (func $no_dce.i64.trunc_s_f32 (param $x f32) (i64.trunc_s/f32 (get_local $x))) 51 | (func $no_dce.i64.trunc_u_f32 (param $x f32) (i64.trunc_u/f32 (get_local $x))) 52 | (func $no_dce.i64.trunc_s_f64 (param $x f64) (i64.trunc_s/f64 (get_local $x))) 53 | (func $no_dce.i64.trunc_u_f64 (param $x f64) (i64.trunc_u/f64 (get_local $x))) 54 | 55 | (export "no_dce.i32.trunc_s_f32" $no_dce.i32.trunc_s_f32) 56 | (export "no_dce.i32.trunc_u_f32" $no_dce.i32.trunc_u_f32) 57 | (export "no_dce.i32.trunc_s_f64" $no_dce.i32.trunc_s_f64) 58 | (export "no_dce.i32.trunc_u_f64" $no_dce.i32.trunc_u_f64) 59 | (export "no_dce.i64.trunc_s_f32" $no_dce.i64.trunc_s_f32) 60 | (export "no_dce.i64.trunc_u_f32" $no_dce.i64.trunc_u_f32) 61 | (export "no_dce.i64.trunc_s_f64" $no_dce.i64.trunc_s_f64) 62 | (export "no_dce.i64.trunc_u_f64" $no_dce.i64.trunc_u_f64) 63 | ) 64 | 65 | (assert_trap (invoke "no_dce.i32.trunc_s_f32" (f32.const nan)) "invalid conversion to integer") 66 | (assert_trap (invoke "no_dce.i32.trunc_u_f32" (f32.const nan)) "invalid conversion to integer") 67 | (assert_trap (invoke "no_dce.i32.trunc_s_f64" (f64.const nan)) "invalid conversion to integer") 68 | (assert_trap (invoke "no_dce.i32.trunc_u_f64" (f64.const nan)) "invalid conversion to integer") 69 | (assert_trap (invoke "no_dce.i64.trunc_s_f32" (f32.const nan)) "invalid conversion to integer") 70 | (assert_trap (invoke "no_dce.i64.trunc_u_f32" (f32.const nan)) "invalid conversion to integer") 71 | (assert_trap (invoke "no_dce.i64.trunc_s_f64" (f64.const nan)) "invalid conversion to integer") 72 | (assert_trap (invoke "no_dce.i64.trunc_u_f64" (f64.const nan)) "invalid conversion to integer") 73 | 74 | (module 75 | (memory 1) 76 | 77 | (export "no_dce.i32.load" $no_dce.i32.load) 78 | (func $no_dce.i32.load (param $i i32) (i32.load (get_local $i))) 79 | (export "no_dce.i64.load" $no_dce.i64.load) 80 | (func $no_dce.i64.load (param $i i32) (i64.load (get_local $i))) 81 | (export "no_dce.f32.load" $no_dce.f32.load) 82 | (func $no_dce.f32.load (param $i i32) (f32.load (get_local $i))) 83 | (export "no_dce.f64.load" $no_dce.f64.load) 84 | (func $no_dce.f64.load (param $i i32) (f64.load (get_local $i))) 85 | ) 86 | 87 | (assert_trap (invoke "no_dce.i32.load" (i32.const 65536)) "out of bounds memory access") 88 | (assert_trap (invoke "no_dce.i64.load" (i32.const 65536)) "out of bounds memory access") 89 | (assert_trap (invoke "no_dce.f32.load" (i32.const 65536)) "out of bounds memory access") 90 | (assert_trap (invoke "no_dce.f64.load" (i32.const 65536)) "out of bounds memory access") 91 | -------------------------------------------------------------------------------- /test/unreachable.wast: -------------------------------------------------------------------------------- 1 | ;; Test `unreachable` operator 2 | 3 | (module 4 | (func $dummy) 5 | 6 | (func "type-i32" (result i32) (unreachable)) 7 | (func "type-i64" (result i32) (unreachable)) 8 | (func "type-f32" (result f64) (unreachable)) 9 | (func "type-f64" (result f64) (unreachable)) 10 | 11 | (func "as-func-first" (result i32) 12 | (unreachable) (i32.const -1) 13 | ) 14 | (func "as-func-mid" (result i32) 15 | (call $dummy) (unreachable) (i32.const -1) 16 | ) 17 | (func "as-func-last" 18 | (call $dummy) (unreachable) 19 | ) 20 | (func "as-func-value" (result i32) 21 | (call $dummy) (unreachable) 22 | ) 23 | 24 | (func "as-block-first" (result i32) 25 | (block (unreachable) (i32.const 2)) 26 | ) 27 | (func "as-block-mid" (result i32) 28 | (block (call $dummy) (unreachable) (i32.const 2)) 29 | ) 30 | (func "as-block-last" 31 | (block (nop) (call $dummy) (unreachable)) 32 | ) 33 | (func "as-block-value" (result i32) 34 | (block (nop) (call $dummy) (unreachable)) 35 | ) 36 | (func "as-block-broke" (result i32) 37 | (block (call $dummy) (br 0 (i32.const 1)) (unreachable)) 38 | ) 39 | 40 | (func "as-loop-first" (result i32) 41 | (loop (unreachable) (i32.const 2)) 42 | ) 43 | (func "as-loop-mid" (result i32) 44 | (loop (call $dummy) (unreachable) (i32.const 2)) 45 | ) 46 | (func "as-loop-last" 47 | (loop (nop) (call $dummy) (unreachable)) 48 | ) 49 | (func "as-loop-broke" (result i32) 50 | (loop (call $dummy) (br 1 (i32.const 1)) (unreachable)) 51 | ) 52 | 53 | (func "as-br-value" (result i32) 54 | (block (br 0 (unreachable))) 55 | ) 56 | 57 | (func "as-br_if-cond" 58 | (block (br_if 0 (unreachable))) 59 | ) 60 | (func "as-br_if-value" (result i32) 61 | (block (br_if 0 (unreachable) (i32.const 1)) (i32.const 7)) 62 | ) 63 | (func "as-br_if-value-cond" (result i32) 64 | (block (br_if 0 (i32.const 6) (unreachable)) (i32.const 7)) 65 | ) 66 | 67 | (func "as-br_table-index" 68 | (block (br_table 0 0 0 (unreachable))) 69 | ) 70 | (func "as-br_table-value" (result i32) 71 | (block (br_table 0 0 0 (unreachable) (i32.const 1)) (i32.const 7)) 72 | ) 73 | (func "as-br_table-value-index" (result i32) 74 | (block (br_table 0 0 (i32.const 6) (unreachable)) (i32.const 7)) 75 | ) 76 | 77 | (func "as-return-value" (result i64) 78 | (return (unreachable)) 79 | ) 80 | 81 | (func "as-if-cond" (result i32) 82 | (if (unreachable) (i32.const 0) (i32.const 1)) 83 | ) 84 | (func "as-if-then" (param i32 i32) (result i32) 85 | (if (get_local 0) (unreachable) (get_local 1)) 86 | ) 87 | (func "as-if-else" (param i32 i32) (result i32) 88 | (if (get_local 0) (get_local 1) (unreachable)) 89 | ) 90 | 91 | (func "as-select-first" (param i32 i32) (result i32) 92 | (select (unreachable) (get_local 0) (get_local 1)) 93 | ) 94 | (func "as-select-second" (param i32 i32) (result i32) 95 | (select (get_local 0) (unreachable) (get_local 1)) 96 | ) 97 | (func "as-select-cond" (result i32) 98 | (select (i32.const 0) (i32.const 1) (unreachable)) 99 | ) 100 | 101 | (func $dummy3 (param i32 i32 i32)) 102 | (func "as-call-first" 103 | (call $dummy3 (unreachable) (i32.const 2) (i32.const 3)) 104 | ) 105 | (func "as-call-mid" 106 | (call $dummy3 (i32.const 1) (unreachable) (i32.const 3)) 107 | ) 108 | (func "as-call-last" 109 | (call $dummy3 (i32.const 1) (i32.const 2) (unreachable)) 110 | ) 111 | 112 | (import "spectest" "print" (param i32 i32 i32)) 113 | (func "as-call_import-first" 114 | (call_import 0 (unreachable) (i32.const 2) (i32.const 3)) 115 | ) 116 | (func "as-call_import-mid" 117 | (call_import 0 (i32.const 1) (unreachable) (i32.const 3)) 118 | ) 119 | (func "as-call_import-last" 120 | (call_import 0 (i32.const 1) (i32.const 2) (unreachable)) 121 | ) 122 | 123 | (type $sig (func (param i32 i32 i32))) 124 | (table $dummy3) 125 | (func "as-call_indirect-func" 126 | (call_indirect $sig (unreachable) (i32.const 1) (i32.const 2) (i32.const 3)) 127 | ) 128 | (func "as-call_indirect-first" 129 | (call_indirect $sig (i32.const 0) (unreachable) (i32.const 2) (i32.const 3)) 130 | ) 131 | (func "as-call_indirect-mid" 132 | (call_indirect $sig (i32.const 0) (i32.const 1) (unreachable) (i32.const 3)) 133 | ) 134 | (func "as-call_indirect-last" 135 | (call_indirect $sig (i32.const 0) (i32.const 1) (i32.const 2) (unreachable)) 136 | ) 137 | 138 | (func "as-set_local-value" (local f32) 139 | (set_local 0 (unreachable)) 140 | ) 141 | 142 | (memory 1) 143 | (func "as-load-address" (result f32) 144 | (f32.load (unreachable)) 145 | ) 146 | (func "as-loadN-address" (result i64) 147 | (i64.load8_s (unreachable)) 148 | ) 149 | 150 | (func "as-store-address" 151 | (f64.store (unreachable) (f64.const 7)) 152 | ) 153 | (func "as-store-value" 154 | (i64.store (i32.const 2) (unreachable)) 155 | ) 156 | 157 | (func "as-storeN-address" 158 | (i32.store8 (unreachable) (i32.const 7)) 159 | ) 160 | (func "as-storeN-value" 161 | (i64.store16 (i32.const 2) (unreachable)) 162 | ) 163 | 164 | (func "as-unary-operand" (result f32) 165 | (f32.neg (unreachable)) 166 | ) 167 | 168 | (func "as-binary-left" (result i32) 169 | (i32.add (unreachable) (i32.const 10)) 170 | ) 171 | (func "as-binary-right" (result i64) 172 | (i64.sub (i64.const 10) (unreachable)) 173 | ) 174 | 175 | (func "as-test-operand" (result i32) 176 | (i32.eqz (unreachable)) 177 | ) 178 | 179 | (func "as-compare-left" (result i32) 180 | (f64.le (unreachable) (f64.const 10)) 181 | ) 182 | (func "as-compare-right" (result i32) 183 | (f32.ne (f32.const 10) (unreachable)) 184 | ) 185 | 186 | (func "as-convert-operand" (result i32) 187 | (i32.wrap/i64 (unreachable)) 188 | ) 189 | 190 | (func "as-grow_memory-size" (result i32) 191 | (grow_memory (unreachable)) 192 | ) 193 | ) 194 | 195 | (assert_trap (invoke "type-i32") "unreachable") 196 | (assert_trap (invoke "type-i64") "unreachable") 197 | (assert_trap (invoke "type-f32") "unreachable") 198 | (assert_trap (invoke "type-f64") "unreachable") 199 | 200 | (assert_trap (invoke "as-func-first") "unreachable") 201 | (assert_trap (invoke "as-func-mid") "unreachable") 202 | (assert_trap (invoke "as-func-last") "unreachable") 203 | (assert_trap (invoke "as-func-value") "unreachable") 204 | 205 | (assert_trap (invoke "as-block-first") "unreachable") 206 | (assert_trap (invoke "as-block-mid") "unreachable") 207 | (assert_trap (invoke "as-block-last") "unreachable") 208 | (assert_trap (invoke "as-block-value") "unreachable") 209 | (assert_return (invoke "as-block-broke") (i32.const 1)) 210 | 211 | (assert_trap (invoke "as-loop-first") "unreachable") 212 | (assert_trap (invoke "as-loop-mid") "unreachable") 213 | (assert_trap (invoke "as-loop-last") "unreachable") 214 | (assert_return (invoke "as-loop-broke") (i32.const 1)) 215 | 216 | (assert_trap (invoke "as-br-value") "unreachable") 217 | 218 | (assert_trap (invoke "as-br_if-cond") "unreachable") 219 | (assert_trap (invoke "as-br_if-value") "unreachable") 220 | (assert_trap (invoke "as-br_if-value-cond") "unreachable") 221 | 222 | (assert_trap (invoke "as-br_table-index") "unreachable") 223 | (assert_trap (invoke "as-br_table-value") "unreachable") 224 | (assert_trap (invoke "as-br_table-value-index") "unreachable") 225 | 226 | (assert_trap (invoke "as-return-value") "unreachable") 227 | 228 | (assert_trap (invoke "as-if-cond") "unreachable") 229 | (assert_trap (invoke "as-if-then" (i32.const 1) (i32.const 6)) "unreachable") 230 | (assert_return (invoke "as-if-then" (i32.const 0) (i32.const 6)) (i32.const 6)) 231 | (assert_trap (invoke "as-if-else" (i32.const 0) (i32.const 6)) "unreachable") 232 | (assert_return (invoke "as-if-else" (i32.const 1) (i32.const 6)) (i32.const 6)) 233 | 234 | (assert_trap (invoke "as-select-first" (i32.const 0) (i32.const 6)) "unreachable") 235 | (assert_trap (invoke "as-select-first" (i32.const 1) (i32.const 6)) "unreachable") 236 | (assert_trap (invoke "as-select-second" (i32.const 0) (i32.const 6)) "unreachable") 237 | (assert_trap (invoke "as-select-second" (i32.const 1) (i32.const 6)) "unreachable") 238 | (assert_trap (invoke "as-select-cond") "unreachable") 239 | 240 | (assert_trap (invoke "as-call-first") "unreachable") 241 | (assert_trap (invoke "as-call-mid") "unreachable") 242 | (assert_trap (invoke "as-call-last") "unreachable") 243 | 244 | (assert_trap (invoke "as-call_import-first") "unreachable") 245 | (assert_trap (invoke "as-call_import-mid") "unreachable") 246 | (assert_trap (invoke "as-call_import-last") "unreachable") 247 | 248 | (assert_trap (invoke "as-call_indirect-func") "unreachable") 249 | (assert_trap (invoke "as-call_indirect-first") "unreachable") 250 | (assert_trap (invoke "as-call_indirect-mid") "unreachable") 251 | (assert_trap (invoke "as-call_indirect-last") "unreachable") 252 | 253 | (assert_trap (invoke "as-set_local-value") "unreachable") 254 | 255 | (assert_trap (invoke "as-load-address") "unreachable") 256 | (assert_trap (invoke "as-loadN-address") "unreachable") 257 | 258 | (assert_trap (invoke "as-store-address") "unreachable") 259 | (assert_trap (invoke "as-store-value") "unreachable") 260 | (assert_trap (invoke "as-storeN-address") "unreachable") 261 | (assert_trap (invoke "as-storeN-value") "unreachable") 262 | 263 | (assert_trap (invoke "as-unary-operand") "unreachable") 264 | 265 | (assert_trap (invoke "as-binary-left") "unreachable") 266 | (assert_trap (invoke "as-binary-right") "unreachable") 267 | 268 | (assert_trap (invoke "as-test-operand") "unreachable") 269 | 270 | (assert_trap (invoke "as-compare-left") "unreachable") 271 | (assert_trap (invoke "as-compare-right") "unreachable") 272 | 273 | (assert_trap (invoke "as-convert-operand") "unreachable") 274 | 275 | (assert_trap (invoke "as-grow_memory-size") "unreachable") 276 | 277 | --------------------------------------------------------------------------------