Add floats
This commit is contained in:
@@ -9,7 +9,7 @@ keywords = ["webassembly", "wasm", "compile", "compiler", "jit"]
|
|||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
arrayvec = "0.4"
|
smallvec = "0.6"
|
||||||
dynasm = "0.2.3"
|
dynasm = "0.2.3"
|
||||||
dynasmrt = "0.2.3"
|
dynasmrt = "0.2.3"
|
||||||
wasmparser = { path = "./wasmparser.rs" }
|
wasmparser = { path = "./wasmparser.rs" }
|
||||||
|
|||||||
710
src/backend.rs
710
src/backend.rs
File diff suppressed because it is too large
Load Diff
@@ -316,8 +316,7 @@ where
|
|||||||
Operator::Ctz(Size::_64) => ctx.i64_ctz(),
|
Operator::Ctz(Size::_64) => ctx.i64_ctz(),
|
||||||
Operator::Popcnt(Size::_64) => ctx.i64_popcnt(),
|
Operator::Popcnt(Size::_64) => ctx.i64_popcnt(),
|
||||||
Operator::Drop(range) => ctx.drop(range),
|
Operator::Drop(range) => ctx.drop(range),
|
||||||
Operator::Const(Value::I32(value)) => ctx.i32_literal(value),
|
Operator::Const(val) => ctx.literal(val),
|
||||||
Operator::Const(Value::I64(value)) => ctx.i64_literal(value),
|
|
||||||
Operator::Load { ty: I32, memarg } => ctx.i32_load(memarg.offset)?,
|
Operator::Load { ty: I32, memarg } => ctx.i32_load(memarg.offset)?,
|
||||||
Operator::Load { ty: I64, memarg } => ctx.i64_load(memarg.offset)?,
|
Operator::Load { ty: I64, memarg } => ctx.i64_load(memarg.offset)?,
|
||||||
Operator::Store { ty: I32, memarg } => ctx.i32_store(memarg.offset)?,
|
Operator::Store { ty: I32, memarg } => ctx.i32_store(memarg.offset)?,
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
#![plugin(dynasm)]
|
#![plugin(dynasm)]
|
||||||
|
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
#[macro_use]
|
||||||
extern crate arrayvec;
|
extern crate smallvec;
|
||||||
extern crate capstone;
|
extern crate capstone;
|
||||||
extern crate either;
|
extern crate either;
|
||||||
extern crate failure;
|
extern crate failure;
|
||||||
|
|||||||
405
src/microwasm.rs
405
src/microwasm.rs
@@ -1,4 +1,5 @@
|
|||||||
use crate::module::ModuleContext;
|
use crate::module::ModuleContext;
|
||||||
|
use smallvec::SmallVec;
|
||||||
use std::{
|
use std::{
|
||||||
fmt,
|
fmt,
|
||||||
iter::{self, FromIterator},
|
iter::{self, FromIterator},
|
||||||
@@ -63,6 +64,56 @@ impl fmt::Display for Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
|
pub fn as_int(self) -> Option<i64> {
|
||||||
|
self.as_i64().or_else(|| self.as_i32().map(|i| i as _))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_bytes(self) -> i64 {
|
||||||
|
match self {
|
||||||
|
Value::I32(val) => val as _,
|
||||||
|
Value::I64(val) => val,
|
||||||
|
Value::F32(val) => val.0 as _,
|
||||||
|
Value::F64(val) => val.0 as _,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_i32(self) -> Option<i32> {
|
||||||
|
match self {
|
||||||
|
Value::I32(val) => Some(val),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_i64(self) -> Option<i64> {
|
||||||
|
match self {
|
||||||
|
Value::I64(val) => Some(val),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_f32(self) -> Option<Ieee32> {
|
||||||
|
match self {
|
||||||
|
Value::F32(val) => Some(val),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_f64(self) -> Option<Ieee64> {
|
||||||
|
match self {
|
||||||
|
Value::F64(val) => Some(val),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_(&self) -> SignlessType {
|
||||||
|
match self {
|
||||||
|
Value::I32(_) => Type::Int(Size::_32),
|
||||||
|
Value::I64(_) => Type::Int(Size::_64),
|
||||||
|
Value::F32(Ieee32(_)) => Type::Float(Size::_32),
|
||||||
|
Value::F64(Ieee64(_)) => Type::Float(Size::_64),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn default_for_type(ty: SignlessType) -> Self {
|
fn default_for_type(ty: SignlessType) -> Self {
|
||||||
match ty {
|
match ty {
|
||||||
Type::Int(Size::_32) => Value::I32(0),
|
Type::Int(Size::_32) => Value::I32(0),
|
||||||
@@ -73,6 +124,37 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<i32> for Value {
|
||||||
|
fn from(other: i32) -> Self {
|
||||||
|
Value::I32(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<i64> for Value {
|
||||||
|
fn from(other: i64) -> Self {
|
||||||
|
Value::I64(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<u32> for Value {
|
||||||
|
fn from(other: u32) -> Self {
|
||||||
|
Value::I32(other as _)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<u64> for Value {
|
||||||
|
fn from(other: u64) -> Self {
|
||||||
|
Value::I64(other as _)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<Ieee32> for Value {
|
||||||
|
fn from(other: Ieee32) -> Self {
|
||||||
|
Value::F32(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<Ieee64> for Value {
|
||||||
|
fn from(other: Ieee64) -> Self {
|
||||||
|
Value::F64(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether to interpret an integer as signed or unsigned
|
/// Whether to interpret an integer as signed or unsigned
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum Signedness {
|
pub enum Signedness {
|
||||||
@@ -697,19 +779,20 @@ impl From<SignlessType> for SigT {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct OpSig {
|
pub struct OpSig {
|
||||||
input: Vec<SigT>,
|
input: SmallVec<[SigT; 3]>,
|
||||||
output: Vec<SigT>,
|
output: SmallVec<[SigT; 3]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OpSig {
|
impl OpSig {
|
||||||
|
#[inline(always)]
|
||||||
fn new<I0, I1>(input: I0, output: I1) -> Self
|
fn new<I0, I1>(input: I0, output: I1) -> Self
|
||||||
where
|
where
|
||||||
I0: IntoIterator<Item = SigT>,
|
I0: IntoIterator<Item = SigT>,
|
||||||
I1: IntoIterator<Item = SigT>,
|
I1: IntoIterator<Item = SigT>,
|
||||||
{
|
{
|
||||||
OpSig {
|
OpSig {
|
||||||
input: Vec::from_iter(input),
|
input: SmallVec::from_iter(input),
|
||||||
output: Vec::from_iter(output),
|
output: SmallVec::from_iter(output),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -741,6 +824,7 @@ where
|
|||||||
use self::SigT::T;
|
use self::SigT::T;
|
||||||
use std::iter::{empty as none, once};
|
use std::iter::{empty as none, once};
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
fn one<A>(a: A) -> impl IntoIterator<Item = SigT>
|
fn one<A>(a: A) -> impl IntoIterator<Item = SigT>
|
||||||
where
|
where
|
||||||
A: Into<SigT>,
|
A: Into<SigT>,
|
||||||
@@ -748,6 +832,7 @@ where
|
|||||||
once(a.into())
|
once(a.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
fn two<A, B>(a: A, b: B) -> impl IntoIterator<Item = SigT>
|
fn two<A, B>(a: A, b: B) -> impl IntoIterator<Item = SigT>
|
||||||
where
|
where
|
||||||
A: Into<SigT>,
|
A: Into<SigT>,
|
||||||
@@ -756,6 +841,7 @@ where
|
|||||||
once(a.into()).chain(once(b.into()))
|
once(a.into()).chain(once(b.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
fn three<A, B, C>(a: A, b: B, c: C) -> impl IntoIterator<Item = SigT>
|
fn three<A, B, C>(a: A, b: B, c: C) -> impl IntoIterator<Item = SigT>
|
||||||
where
|
where
|
||||||
A: Into<SigT>,
|
A: Into<SigT>,
|
||||||
@@ -1124,10 +1210,9 @@ impl<'a, 'b, M: ModuleContext> Iterator for MicrowasmConv<'a, 'b, M>
|
|||||||
where
|
where
|
||||||
for<'any> &'any M::Signature: Into<OpSig>,
|
for<'any> &'any M::Signature: Into<OpSig>,
|
||||||
{
|
{
|
||||||
type Item = wasmparser::Result<Vec<OperatorFromWasm>>;
|
type Item = wasmparser::Result<SmallVec<[OperatorFromWasm; 1]>>;
|
||||||
|
|
||||||
// TODO: We don't need to use vec here, we can maybe use `ArrayVec` or `Option`+`chain`
|
fn next(&mut self) -> Option<wasmparser::Result<SmallVec<[OperatorFromWasm; 1]>>> {
|
||||||
fn next(&mut self) -> Option<wasmparser::Result<Vec<OperatorFromWasm>>> {
|
|
||||||
macro_rules! to_drop {
|
macro_rules! to_drop {
|
||||||
($block:expr) => {{
|
($block:expr) => {{
|
||||||
let first_non_local_depth = $block.returns;
|
let first_non_local_depth = $block.returns;
|
||||||
@@ -1154,7 +1239,7 @@ where
|
|||||||
return Some(Ok(consts
|
return Some(Ok(consts
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|value| Operator::Const(value))
|
.map(|value| Operator::Const(value))
|
||||||
.collect::<Vec<_>>()));
|
.collect()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.unreachable {
|
if self.unreachable {
|
||||||
@@ -1185,7 +1270,7 @@ where
|
|||||||
*has_else = true;
|
*has_else = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
break vec![Operator::Label((block.id, NameTag::Else))];
|
break smallvec![Operator::Label((block.id, NameTag::Else))];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WasmOperator::End => {
|
WasmOperator::End => {
|
||||||
@@ -1209,7 +1294,7 @@ where
|
|||||||
{
|
{
|
||||||
self.stack = block.params().unwrap().to_vec();
|
self.stack = block.params().unwrap().to_vec();
|
||||||
|
|
||||||
break vec![
|
break smallvec![
|
||||||
Operator::Label((block.id, NameTag::Else)),
|
Operator::Label((block.id, NameTag::Else)),
|
||||||
Operator::Br {
|
Operator::Br {
|
||||||
target: BrTarget::Label(end_label),
|
target: BrTarget::Label(end_label),
|
||||||
@@ -1217,7 +1302,7 @@ where
|
|||||||
Operator::Label(end_label),
|
Operator::Label(end_label),
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
break vec![Operator::Label((block.id, NameTag::End))];
|
break smallvec![Operator::Label((block.id, NameTag::End))];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
depth -= 1;
|
depth -= 1;
|
||||||
@@ -1240,9 +1325,9 @@ where
|
|||||||
Some(Ok(match op {
|
Some(Ok(match op {
|
||||||
WasmOperator::Unreachable => {
|
WasmOperator::Unreachable => {
|
||||||
self.unreachable = true;
|
self.unreachable = true;
|
||||||
vec![Operator::Unreachable]
|
smallvec![Operator::Unreachable]
|
||||||
}
|
}
|
||||||
WasmOperator::Nop => vec![],
|
WasmOperator::Nop => smallvec![],
|
||||||
WasmOperator::Block { ty } => {
|
WasmOperator::Block { ty } => {
|
||||||
let id = self.next_id();
|
let id = self.next_id();
|
||||||
self.control_frames.push(ControlFrame {
|
self.control_frames.push(ControlFrame {
|
||||||
@@ -1256,7 +1341,7 @@ where
|
|||||||
needs_end_label: false,
|
needs_end_label: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
vec![Operator::end(
|
smallvec![Operator::end(
|
||||||
self.block_params_with_wasm_type(ty),
|
self.block_params_with_wasm_type(ty),
|
||||||
(id, NameTag::End),
|
(id, NameTag::End),
|
||||||
)]
|
)]
|
||||||
@@ -1273,7 +1358,7 @@ where
|
|||||||
kind: ControlFrameKind::Loop,
|
kind: ControlFrameKind::Loop,
|
||||||
});
|
});
|
||||||
let label = (id, NameTag::Header);
|
let label = (id, NameTag::Header);
|
||||||
vec![
|
smallvec![
|
||||||
Operator::loop_(self.block_params(), label),
|
Operator::loop_(self.block_params(), label),
|
||||||
Operator::end(self.block_params_with_wasm_type(ty), (id, NameTag::End)),
|
Operator::end(self.block_params_with_wasm_type(ty), (id, NameTag::End)),
|
||||||
Operator::Br {
|
Operator::Br {
|
||||||
@@ -1302,7 +1387,7 @@ where
|
|||||||
(id, NameTag::Else),
|
(id, NameTag::Else),
|
||||||
(id, NameTag::End),
|
(id, NameTag::End),
|
||||||
);
|
);
|
||||||
vec![
|
smallvec![
|
||||||
Operator::block(self.block_params(), then),
|
Operator::block(self.block_params(), then),
|
||||||
Operator::block(self.block_params(), else_),
|
Operator::block(self.block_params(), else_),
|
||||||
Operator::end(self.block_params_with_wasm_type(ty), end),
|
Operator::end(self.block_params_with_wasm_type(ty), end),
|
||||||
@@ -1326,7 +1411,7 @@ where
|
|||||||
|
|
||||||
let label = (block.id, NameTag::Else);
|
let label = (block.id, NameTag::Else);
|
||||||
|
|
||||||
Vec::from_iter(
|
SmallVec::from_iter(
|
||||||
to_drop
|
to_drop
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(Operator::Drop)
|
.map(Operator::Drop)
|
||||||
@@ -1357,7 +1442,7 @@ where
|
|||||||
to_drop
|
to_drop
|
||||||
.map(Operator::Drop)
|
.map(Operator::Drop)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(vec![
|
.chain::<SmallVec<[_; 4]>>(smallvec![
|
||||||
Operator::Br {
|
Operator::Br {
|
||||||
target: BrTarget::Label(else_),
|
target: BrTarget::Label(else_),
|
||||||
},
|
},
|
||||||
@@ -1369,7 +1454,7 @@ where
|
|||||||
])
|
])
|
||||||
.collect()
|
.collect()
|
||||||
} else {
|
} else {
|
||||||
Vec::from_iter(if self.control_frames.is_empty() {
|
SmallVec::from_iter(if self.control_frames.is_empty() {
|
||||||
self.is_done = true;
|
self.is_done = true;
|
||||||
|
|
||||||
None.into_iter()
|
None.into_iter()
|
||||||
@@ -1405,7 +1490,7 @@ where
|
|||||||
|
|
||||||
let block = self.nth_block_mut(relative_depth as _);
|
let block = self.nth_block_mut(relative_depth as _);
|
||||||
block.mark_branched_to();
|
block.mark_branched_to();
|
||||||
Vec::from_iter(to_drop.into_iter().map(Operator::Drop).chain(iter::once(
|
SmallVec::from_iter(to_drop.into_iter().map(Operator::Drop).chain(iter::once(
|
||||||
Operator::Br {
|
Operator::Br {
|
||||||
target: block.br_target(),
|
target: block.br_target(),
|
||||||
},
|
},
|
||||||
@@ -1424,7 +1509,7 @@ where
|
|||||||
// us to generate a spurious `jmp`.
|
// us to generate a spurious `jmp`.
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
} else {
|
} else {
|
||||||
vec![
|
smallvec![
|
||||||
Operator::block(params, label),
|
Operator::block(params, label),
|
||||||
Operator::BrIf {
|
Operator::BrIf {
|
||||||
then: block.br_target(),
|
then: block.br_target(),
|
||||||
@@ -1441,212 +1526,214 @@ where
|
|||||||
let block = self.function_block();
|
let block = self.function_block();
|
||||||
let to_drop = to_drop!(block);
|
let to_drop = to_drop!(block);
|
||||||
|
|
||||||
Vec::from_iter(to_drop.into_iter().map(Operator::Drop).chain(iter::once(
|
SmallVec::from_iter(to_drop.into_iter().map(Operator::Drop).chain(iter::once(
|
||||||
Operator::Br {
|
Operator::Br {
|
||||||
target: block.br_target(),
|
target: block.br_target(),
|
||||||
},
|
},
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
WasmOperator::Call { function_index } => vec![Operator::Call { function_index }],
|
WasmOperator::Call { function_index } => smallvec![Operator::Call { function_index }],
|
||||||
WasmOperator::CallIndirect { index, table_index } => vec![Operator::CallIndirect {
|
WasmOperator::CallIndirect { index, table_index } => {
|
||||||
type_index: index,
|
smallvec![Operator::CallIndirect {
|
||||||
table_index,
|
type_index: index,
|
||||||
}],
|
table_index,
|
||||||
WasmOperator::Drop => vec![Operator::Drop(0..=0)],
|
}]
|
||||||
WasmOperator::Select => vec![Operator::Select],
|
}
|
||||||
|
WasmOperator::Drop => smallvec![Operator::Drop(0..=0)],
|
||||||
|
WasmOperator::Select => smallvec![Operator::Select],
|
||||||
|
|
||||||
WasmOperator::GetLocal { local_index } => {
|
WasmOperator::GetLocal { local_index } => {
|
||||||
// TODO: `- 1` because we apply the stack difference _before_ this point
|
// TODO: `- 1` because we apply the stack difference _before_ this point
|
||||||
let depth = self.local_depth(local_index) - 1;
|
let depth = self.local_depth(local_index) - 1;
|
||||||
vec![Operator::Pick { depth }]
|
smallvec![Operator::Pick { depth }]
|
||||||
}
|
}
|
||||||
WasmOperator::SetLocal { local_index } => {
|
WasmOperator::SetLocal { local_index } => {
|
||||||
// TODO: `+ 1` because we apply the stack difference _before_ this point
|
// TODO: `+ 1` because we apply the stack difference _before_ this point
|
||||||
let depth = self.local_depth(local_index) + 1;
|
let depth = self.local_depth(local_index) + 1;
|
||||||
vec![Operator::Swap { depth }, Operator::Drop(0..=0)]
|
smallvec![Operator::Swap { depth }, Operator::Drop(0..=0)]
|
||||||
}
|
}
|
||||||
WasmOperator::TeeLocal { local_index } => {
|
WasmOperator::TeeLocal { local_index } => {
|
||||||
let depth = self.local_depth(local_index);
|
let depth = self.local_depth(local_index);
|
||||||
vec![
|
smallvec![
|
||||||
Operator::Swap { depth },
|
Operator::Swap { depth },
|
||||||
Operator::Drop(0..=0),
|
Operator::Drop(0..=0),
|
||||||
Operator::Pick { depth: depth - 1 },
|
Operator::Pick { depth: depth - 1 },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
WasmOperator::I32Load { memarg } => vec![Operator::Load { ty: I32, memarg }],
|
WasmOperator::I32Load { memarg } => smallvec![Operator::Load { ty: I32, memarg }],
|
||||||
WasmOperator::I64Load { memarg } => vec![Operator::Load { ty: I64, memarg }],
|
WasmOperator::I64Load { memarg } => smallvec![Operator::Load { ty: I64, memarg }],
|
||||||
WasmOperator::F32Load { memarg } => vec![Operator::Load { ty: F32, memarg }],
|
WasmOperator::F32Load { memarg } => smallvec![Operator::Load { ty: F32, memarg }],
|
||||||
WasmOperator::F64Load { memarg } => vec![Operator::Load { ty: F64, memarg }],
|
WasmOperator::F64Load { memarg } => smallvec![Operator::Load { ty: F64, memarg }],
|
||||||
WasmOperator::I32Load8S { memarg } => vec![Operator::Load8 {
|
WasmOperator::I32Load8S { memarg } => smallvec![Operator::Load8 {
|
||||||
ty: sint::I32,
|
ty: sint::I32,
|
||||||
memarg,
|
memarg,
|
||||||
}],
|
}],
|
||||||
WasmOperator::I32Load8U { memarg } => vec![Operator::Load8 {
|
WasmOperator::I32Load8U { memarg } => smallvec![Operator::Load8 {
|
||||||
ty: sint::U32,
|
ty: sint::U32,
|
||||||
memarg,
|
memarg,
|
||||||
}],
|
}],
|
||||||
WasmOperator::I32Load16S { memarg } => vec![Operator::Load16 {
|
WasmOperator::I32Load16S { memarg } => smallvec![Operator::Load16 {
|
||||||
ty: sint::I32,
|
ty: sint::I32,
|
||||||
memarg,
|
memarg,
|
||||||
}],
|
}],
|
||||||
WasmOperator::I32Load16U { memarg } => vec![Operator::Load16 {
|
WasmOperator::I32Load16U { memarg } => smallvec![Operator::Load16 {
|
||||||
ty: sint::U32,
|
ty: sint::U32,
|
||||||
memarg,
|
memarg,
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Load8S { memarg } => vec![Operator::Load8 {
|
WasmOperator::I64Load8S { memarg } => smallvec![Operator::Load8 {
|
||||||
ty: sint::I64,
|
ty: sint::I64,
|
||||||
memarg,
|
memarg,
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Load8U { memarg } => vec![Operator::Load8 {
|
WasmOperator::I64Load8U { memarg } => smallvec![Operator::Load8 {
|
||||||
ty: sint::U64,
|
ty: sint::U64,
|
||||||
memarg,
|
memarg,
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Load16S { memarg } => vec![Operator::Load16 {
|
WasmOperator::I64Load16S { memarg } => smallvec![Operator::Load16 {
|
||||||
ty: sint::I64,
|
ty: sint::I64,
|
||||||
memarg,
|
memarg,
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Load16U { memarg } => vec![Operator::Load16 {
|
WasmOperator::I64Load16U { memarg } => smallvec![Operator::Load16 {
|
||||||
ty: sint::U64,
|
ty: sint::U64,
|
||||||
memarg,
|
memarg,
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Load32S { memarg } => vec![Operator::Load32 {
|
WasmOperator::I64Load32S { memarg } => smallvec![Operator::Load32 {
|
||||||
sign: Signedness::Signed,
|
sign: Signedness::Signed,
|
||||||
memarg,
|
memarg,
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Load32U { memarg } => vec![Operator::Load32 {
|
WasmOperator::I64Load32U { memarg } => smallvec![Operator::Load32 {
|
||||||
sign: Signedness::Unsigned,
|
sign: Signedness::Unsigned,
|
||||||
memarg,
|
memarg,
|
||||||
}],
|
}],
|
||||||
|
|
||||||
WasmOperator::I32Store { memarg } => vec![Operator::Store { ty: I32, memarg }],
|
WasmOperator::I32Store { memarg } => smallvec![Operator::Store { ty: I32, memarg }],
|
||||||
WasmOperator::I64Store { memarg } => vec![Operator::Store { ty: I64, memarg }],
|
WasmOperator::I64Store { memarg } => smallvec![Operator::Store { ty: I64, memarg }],
|
||||||
WasmOperator::F32Store { memarg } => vec![Operator::Store { ty: F32, memarg }],
|
WasmOperator::F32Store { memarg } => smallvec![Operator::Store { ty: F32, memarg }],
|
||||||
WasmOperator::F64Store { memarg } => vec![Operator::Store { ty: F64, memarg }],
|
WasmOperator::F64Store { memarg } => smallvec![Operator::Store { ty: F64, memarg }],
|
||||||
|
|
||||||
WasmOperator::I32Store8 { memarg } => vec![Operator::Store8 {
|
WasmOperator::I32Store8 { memarg } => smallvec![Operator::Store8 {
|
||||||
ty: Size::_32,
|
ty: Size::_32,
|
||||||
memarg,
|
memarg,
|
||||||
}],
|
}],
|
||||||
WasmOperator::I32Store16 { memarg } => vec![Operator::Store16 {
|
WasmOperator::I32Store16 { memarg } => smallvec![Operator::Store16 {
|
||||||
ty: Size::_32,
|
ty: Size::_32,
|
||||||
memarg,
|
memarg,
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Store8 { memarg } => vec![Operator::Store8 {
|
WasmOperator::I64Store8 { memarg } => smallvec![Operator::Store8 {
|
||||||
ty: Size::_64,
|
ty: Size::_64,
|
||||||
memarg,
|
memarg,
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Store16 { memarg } => vec![Operator::Store16 {
|
WasmOperator::I64Store16 { memarg } => smallvec![Operator::Store16 {
|
||||||
ty: Size::_64,
|
ty: Size::_64,
|
||||||
memarg,
|
memarg,
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Store32 { memarg } => vec![Operator::Store32 { memarg }],
|
WasmOperator::I64Store32 { memarg } => smallvec![Operator::Store32 { memarg }],
|
||||||
WasmOperator::MemorySize { reserved } => vec![Operator::MemorySize { reserved }],
|
WasmOperator::MemorySize { reserved } => smallvec![Operator::MemorySize { reserved }],
|
||||||
WasmOperator::MemoryGrow { reserved } => vec![Operator::MemoryGrow { reserved }],
|
WasmOperator::MemoryGrow { reserved } => smallvec![Operator::MemoryGrow { reserved }],
|
||||||
WasmOperator::I32Const { value } => vec![Operator::Const(Value::I32(value))],
|
WasmOperator::I32Const { value } => smallvec![Operator::Const(Value::I32(value))],
|
||||||
WasmOperator::I64Const { value } => vec![Operator::Const(Value::I64(value))],
|
WasmOperator::I64Const { value } => smallvec![Operator::Const(Value::I64(value))],
|
||||||
WasmOperator::F32Const { value } => vec![Operator::Const(Value::F32(value))],
|
WasmOperator::F32Const { value } => smallvec![Operator::Const(Value::F32(value))],
|
||||||
WasmOperator::F64Const { value } => vec![Operator::Const(Value::F64(value))],
|
WasmOperator::F64Const { value } => smallvec![Operator::Const(Value::F64(value))],
|
||||||
WasmOperator::RefNull => unimplemented!(),
|
WasmOperator::RefNull => unimplemented!(),
|
||||||
WasmOperator::RefIsNull => unimplemented!(),
|
WasmOperator::RefIsNull => unimplemented!(),
|
||||||
WasmOperator::I32Eqz => vec![Operator::Eqz(Size::_32)],
|
WasmOperator::I32Eqz => smallvec![Operator::Eqz(Size::_32)],
|
||||||
WasmOperator::I32Eq => vec![Operator::Eq(I32)],
|
WasmOperator::I32Eq => smallvec![Operator::Eq(I32)],
|
||||||
WasmOperator::I32Ne => vec![Operator::Ne(I32)],
|
WasmOperator::I32Ne => smallvec![Operator::Ne(I32)],
|
||||||
WasmOperator::I32LtS => vec![Operator::Lt(SI32)],
|
WasmOperator::I32LtS => smallvec![Operator::Lt(SI32)],
|
||||||
WasmOperator::I32LtU => vec![Operator::Lt(SU32)],
|
WasmOperator::I32LtU => smallvec![Operator::Lt(SU32)],
|
||||||
WasmOperator::I32GtS => vec![Operator::Gt(SI32)],
|
WasmOperator::I32GtS => smallvec![Operator::Gt(SI32)],
|
||||||
WasmOperator::I32GtU => vec![Operator::Gt(SU32)],
|
WasmOperator::I32GtU => smallvec![Operator::Gt(SU32)],
|
||||||
WasmOperator::I32LeS => vec![Operator::Le(SI32)],
|
WasmOperator::I32LeS => smallvec![Operator::Le(SI32)],
|
||||||
WasmOperator::I32LeU => vec![Operator::Le(SU32)],
|
WasmOperator::I32LeU => smallvec![Operator::Le(SU32)],
|
||||||
WasmOperator::I32GeS => vec![Operator::Ge(SI32)],
|
WasmOperator::I32GeS => smallvec![Operator::Ge(SI32)],
|
||||||
WasmOperator::I32GeU => vec![Operator::Ge(SU32)],
|
WasmOperator::I32GeU => smallvec![Operator::Ge(SU32)],
|
||||||
WasmOperator::I64Eqz => vec![Operator::Eqz(Size::_64)],
|
WasmOperator::I64Eqz => smallvec![Operator::Eqz(Size::_64)],
|
||||||
WasmOperator::I64Eq => vec![Operator::Eq(I64)],
|
WasmOperator::I64Eq => smallvec![Operator::Eq(I64)],
|
||||||
WasmOperator::I64Ne => vec![Operator::Ne(I64)],
|
WasmOperator::I64Ne => smallvec![Operator::Ne(I64)],
|
||||||
WasmOperator::I64LtS => vec![Operator::Lt(SI64)],
|
WasmOperator::I64LtS => smallvec![Operator::Lt(SI64)],
|
||||||
WasmOperator::I64LtU => vec![Operator::Lt(SU64)],
|
WasmOperator::I64LtU => smallvec![Operator::Lt(SU64)],
|
||||||
WasmOperator::I64GtS => vec![Operator::Gt(SI64)],
|
WasmOperator::I64GtS => smallvec![Operator::Gt(SI64)],
|
||||||
WasmOperator::I64GtU => vec![Operator::Gt(SU64)],
|
WasmOperator::I64GtU => smallvec![Operator::Gt(SU64)],
|
||||||
WasmOperator::I64LeS => vec![Operator::Le(SI64)],
|
WasmOperator::I64LeS => smallvec![Operator::Le(SI64)],
|
||||||
WasmOperator::I64LeU => vec![Operator::Le(SU64)],
|
WasmOperator::I64LeU => smallvec![Operator::Le(SU64)],
|
||||||
WasmOperator::I64GeS => vec![Operator::Ge(SI64)],
|
WasmOperator::I64GeS => smallvec![Operator::Ge(SI64)],
|
||||||
WasmOperator::I64GeU => vec![Operator::Ge(SU64)],
|
WasmOperator::I64GeU => smallvec![Operator::Ge(SU64)],
|
||||||
WasmOperator::F32Eq => vec![Operator::Eq(F32)],
|
WasmOperator::F32Eq => smallvec![Operator::Eq(F32)],
|
||||||
WasmOperator::F32Ne => vec![Operator::Ne(F32)],
|
WasmOperator::F32Ne => smallvec![Operator::Ne(F32)],
|
||||||
WasmOperator::F32Lt => vec![Operator::Lt(SF32)],
|
WasmOperator::F32Lt => smallvec![Operator::Lt(SF32)],
|
||||||
WasmOperator::F32Gt => vec![Operator::Gt(SF32)],
|
WasmOperator::F32Gt => smallvec![Operator::Gt(SF32)],
|
||||||
WasmOperator::F32Le => vec![Operator::Le(SF32)],
|
WasmOperator::F32Le => smallvec![Operator::Le(SF32)],
|
||||||
WasmOperator::F32Ge => vec![Operator::Ge(SF32)],
|
WasmOperator::F32Ge => smallvec![Operator::Ge(SF32)],
|
||||||
WasmOperator::F64Eq => vec![Operator::Eq(F64)],
|
WasmOperator::F64Eq => smallvec![Operator::Eq(F64)],
|
||||||
WasmOperator::F64Ne => vec![Operator::Ne(F64)],
|
WasmOperator::F64Ne => smallvec![Operator::Ne(F64)],
|
||||||
WasmOperator::F64Lt => vec![Operator::Lt(SF64)],
|
WasmOperator::F64Lt => smallvec![Operator::Lt(SF64)],
|
||||||
WasmOperator::F64Gt => vec![Operator::Gt(SF64)],
|
WasmOperator::F64Gt => smallvec![Operator::Gt(SF64)],
|
||||||
WasmOperator::F64Le => vec![Operator::Le(SF64)],
|
WasmOperator::F64Le => smallvec![Operator::Le(SF64)],
|
||||||
WasmOperator::F64Ge => vec![Operator::Ge(SF64)],
|
WasmOperator::F64Ge => smallvec![Operator::Ge(SF64)],
|
||||||
WasmOperator::I32Clz => vec![Operator::Clz(Size::_32)],
|
WasmOperator::I32Clz => smallvec![Operator::Clz(Size::_32)],
|
||||||
WasmOperator::I32Ctz => vec![Operator::Ctz(Size::_32)],
|
WasmOperator::I32Ctz => smallvec![Operator::Ctz(Size::_32)],
|
||||||
WasmOperator::I32Popcnt => vec![Operator::Popcnt(Size::_32)],
|
WasmOperator::I32Popcnt => smallvec![Operator::Popcnt(Size::_32)],
|
||||||
WasmOperator::I32Add => vec![Operator::Add(I32)],
|
WasmOperator::I32Add => smallvec![Operator::Add(I32)],
|
||||||
WasmOperator::I32Sub => vec![Operator::Sub(I32)],
|
WasmOperator::I32Sub => smallvec![Operator::Sub(I32)],
|
||||||
WasmOperator::I32Mul => vec![Operator::Mul(I32)],
|
WasmOperator::I32Mul => smallvec![Operator::Mul(I32)],
|
||||||
WasmOperator::I32DivS => vec![Operator::Div(SI32)],
|
WasmOperator::I32DivS => smallvec![Operator::Div(SI32)],
|
||||||
WasmOperator::I32DivU => vec![Operator::Div(SU32)],
|
WasmOperator::I32DivU => smallvec![Operator::Div(SU32)],
|
||||||
WasmOperator::I32RemS => vec![Operator::Rem(sint::I32)],
|
WasmOperator::I32RemS => smallvec![Operator::Rem(sint::I32)],
|
||||||
WasmOperator::I32RemU => vec![Operator::Rem(sint::U32)],
|
WasmOperator::I32RemU => smallvec![Operator::Rem(sint::U32)],
|
||||||
WasmOperator::I32And => vec![Operator::And(Size::_32)],
|
WasmOperator::I32And => smallvec![Operator::And(Size::_32)],
|
||||||
WasmOperator::I32Or => vec![Operator::Or(Size::_32)],
|
WasmOperator::I32Or => smallvec![Operator::Or(Size::_32)],
|
||||||
WasmOperator::I32Xor => vec![Operator::Xor(Size::_32)],
|
WasmOperator::I32Xor => smallvec![Operator::Xor(Size::_32)],
|
||||||
WasmOperator::I32Shl => vec![Operator::Shl(Size::_32)],
|
WasmOperator::I32Shl => smallvec![Operator::Shl(Size::_32)],
|
||||||
WasmOperator::I32ShrS => vec![Operator::Shr(sint::I32)],
|
WasmOperator::I32ShrS => smallvec![Operator::Shr(sint::I32)],
|
||||||
WasmOperator::I32ShrU => vec![Operator::Shr(sint::U32)],
|
WasmOperator::I32ShrU => smallvec![Operator::Shr(sint::U32)],
|
||||||
WasmOperator::I32Rotl => vec![Operator::Rotl(Size::_32)],
|
WasmOperator::I32Rotl => smallvec![Operator::Rotl(Size::_32)],
|
||||||
WasmOperator::I32Rotr => vec![Operator::Rotr(Size::_32)],
|
WasmOperator::I32Rotr => smallvec![Operator::Rotr(Size::_32)],
|
||||||
WasmOperator::I64Clz => vec![Operator::Clz(Size::_64)],
|
WasmOperator::I64Clz => smallvec![Operator::Clz(Size::_64)],
|
||||||
WasmOperator::I64Ctz => vec![Operator::Ctz(Size::_64)],
|
WasmOperator::I64Ctz => smallvec![Operator::Ctz(Size::_64)],
|
||||||
WasmOperator::I64Popcnt => vec![Operator::Popcnt(Size::_64)],
|
WasmOperator::I64Popcnt => smallvec![Operator::Popcnt(Size::_64)],
|
||||||
WasmOperator::I64Add => vec![Operator::Add(I64)],
|
WasmOperator::I64Add => smallvec![Operator::Add(I64)],
|
||||||
WasmOperator::I64Sub => vec![Operator::Sub(I64)],
|
WasmOperator::I64Sub => smallvec![Operator::Sub(I64)],
|
||||||
WasmOperator::I64Mul => vec![Operator::Mul(I64)],
|
WasmOperator::I64Mul => smallvec![Operator::Mul(I64)],
|
||||||
WasmOperator::I64DivS => vec![Operator::Div(SI64)],
|
WasmOperator::I64DivS => smallvec![Operator::Div(SI64)],
|
||||||
WasmOperator::I64DivU => vec![Operator::Div(SU64)],
|
WasmOperator::I64DivU => smallvec![Operator::Div(SU64)],
|
||||||
WasmOperator::I64RemS => vec![Operator::Rem(sint::I64)],
|
WasmOperator::I64RemS => smallvec![Operator::Rem(sint::I64)],
|
||||||
WasmOperator::I64RemU => vec![Operator::Rem(sint::U64)],
|
WasmOperator::I64RemU => smallvec![Operator::Rem(sint::U64)],
|
||||||
WasmOperator::I64And => vec![Operator::And(Size::_64)],
|
WasmOperator::I64And => smallvec![Operator::And(Size::_64)],
|
||||||
WasmOperator::I64Or => vec![Operator::Or(Size::_64)],
|
WasmOperator::I64Or => smallvec![Operator::Or(Size::_64)],
|
||||||
WasmOperator::I64Xor => vec![Operator::Xor(Size::_64)],
|
WasmOperator::I64Xor => smallvec![Operator::Xor(Size::_64)],
|
||||||
WasmOperator::I64Shl => vec![Operator::Shl(Size::_64)],
|
WasmOperator::I64Shl => smallvec![Operator::Shl(Size::_64)],
|
||||||
WasmOperator::I64ShrS => vec![Operator::Shr(sint::I64)],
|
WasmOperator::I64ShrS => smallvec![Operator::Shr(sint::I64)],
|
||||||
WasmOperator::I64ShrU => vec![Operator::Shr(sint::U64)],
|
WasmOperator::I64ShrU => smallvec![Operator::Shr(sint::U64)],
|
||||||
WasmOperator::I64Rotl => vec![Operator::Rotl(Size::_64)],
|
WasmOperator::I64Rotl => smallvec![Operator::Rotl(Size::_64)],
|
||||||
WasmOperator::I64Rotr => vec![Operator::Rotr(Size::_64)],
|
WasmOperator::I64Rotr => smallvec![Operator::Rotr(Size::_64)],
|
||||||
WasmOperator::F32Abs => vec![Operator::Abs(Size::_32)],
|
WasmOperator::F32Abs => smallvec![Operator::Abs(Size::_32)],
|
||||||
WasmOperator::F32Neg => vec![Operator::Neg(Size::_32)],
|
WasmOperator::F32Neg => smallvec![Operator::Neg(Size::_32)],
|
||||||
WasmOperator::F32Ceil => vec![Operator::Ceil(Size::_32)],
|
WasmOperator::F32Ceil => smallvec![Operator::Ceil(Size::_32)],
|
||||||
WasmOperator::F32Floor => vec![Operator::Floor(Size::_32)],
|
WasmOperator::F32Floor => smallvec![Operator::Floor(Size::_32)],
|
||||||
WasmOperator::F32Trunc => vec![Operator::Trunc(Size::_32)],
|
WasmOperator::F32Trunc => smallvec![Operator::Trunc(Size::_32)],
|
||||||
WasmOperator::F32Nearest => vec![Operator::Nearest(Size::_32)],
|
WasmOperator::F32Nearest => smallvec![Operator::Nearest(Size::_32)],
|
||||||
WasmOperator::F32Sqrt => vec![Operator::Sqrt(Size::_32)],
|
WasmOperator::F32Sqrt => smallvec![Operator::Sqrt(Size::_32)],
|
||||||
WasmOperator::F32Add => vec![Operator::Add(F32)],
|
WasmOperator::F32Add => smallvec![Operator::Add(F32)],
|
||||||
WasmOperator::F32Sub => vec![Operator::Sub(F32)],
|
WasmOperator::F32Sub => smallvec![Operator::Sub(F32)],
|
||||||
WasmOperator::F32Mul => vec![Operator::Mul(F32)],
|
WasmOperator::F32Mul => smallvec![Operator::Mul(F32)],
|
||||||
WasmOperator::F32Div => vec![Operator::Div(SF32)],
|
WasmOperator::F32Div => smallvec![Operator::Div(SF32)],
|
||||||
WasmOperator::F32Min => vec![Operator::Min(Size::_32)],
|
WasmOperator::F32Min => smallvec![Operator::Min(Size::_32)],
|
||||||
WasmOperator::F32Max => vec![Operator::Max(Size::_32)],
|
WasmOperator::F32Max => smallvec![Operator::Max(Size::_32)],
|
||||||
WasmOperator::F32Copysign => vec![Operator::Copysign(Size::_32)],
|
WasmOperator::F32Copysign => smallvec![Operator::Copysign(Size::_32)],
|
||||||
WasmOperator::F64Abs => vec![Operator::Abs(Size::_64)],
|
WasmOperator::F64Abs => smallvec![Operator::Abs(Size::_64)],
|
||||||
WasmOperator::F64Neg => vec![Operator::Neg(Size::_64)],
|
WasmOperator::F64Neg => smallvec![Operator::Neg(Size::_64)],
|
||||||
WasmOperator::F64Ceil => vec![Operator::Ceil(Size::_64)],
|
WasmOperator::F64Ceil => smallvec![Operator::Ceil(Size::_64)],
|
||||||
WasmOperator::F64Floor => vec![Operator::Floor(Size::_64)],
|
WasmOperator::F64Floor => smallvec![Operator::Floor(Size::_64)],
|
||||||
WasmOperator::F64Trunc => vec![Operator::Trunc(Size::_64)],
|
WasmOperator::F64Trunc => smallvec![Operator::Trunc(Size::_64)],
|
||||||
WasmOperator::F64Nearest => vec![Operator::Nearest(Size::_64)],
|
WasmOperator::F64Nearest => smallvec![Operator::Nearest(Size::_64)],
|
||||||
WasmOperator::F64Sqrt => vec![Operator::Sqrt(Size::_64)],
|
WasmOperator::F64Sqrt => smallvec![Operator::Sqrt(Size::_64)],
|
||||||
WasmOperator::F64Add => vec![Operator::Add(F64)],
|
WasmOperator::F64Add => smallvec![Operator::Add(F64)],
|
||||||
WasmOperator::F64Sub => vec![Operator::Sub(F64)],
|
WasmOperator::F64Sub => smallvec![Operator::Sub(F64)],
|
||||||
WasmOperator::F64Mul => vec![Operator::Mul(F64)],
|
WasmOperator::F64Mul => smallvec![Operator::Mul(F64)],
|
||||||
WasmOperator::F64Div => vec![Operator::Div(SF64)],
|
WasmOperator::F64Div => smallvec![Operator::Div(SF64)],
|
||||||
WasmOperator::F64Min => vec![Operator::Min(Size::_64)],
|
WasmOperator::F64Min => smallvec![Operator::Min(Size::_64)],
|
||||||
WasmOperator::F64Max => vec![Operator::Max(Size::_64)],
|
WasmOperator::F64Max => smallvec![Operator::Max(Size::_64)],
|
||||||
WasmOperator::F64Copysign => vec![Operator::Copysign(Size::_64)],
|
WasmOperator::F64Copysign => smallvec![Operator::Copysign(Size::_64)],
|
||||||
WasmOperator::I32WrapI64 => unimplemented!(),
|
WasmOperator::I32WrapI64 => unimplemented!(),
|
||||||
WasmOperator::I32TruncSF32 => unimplemented!(),
|
WasmOperator::I32TruncSF32 => unimplemented!(),
|
||||||
WasmOperator::I32TruncUF32 => unimplemented!(),
|
WasmOperator::I32TruncUF32 => unimplemented!(),
|
||||||
|
|||||||
426
src/tests.rs
426
src/tests.rs
@@ -729,19 +729,70 @@ fn brif_block_passthru() {
|
|||||||
assert_eq!(execute_wat(code, 0, 3), 6);
|
assert_eq!(execute_wat(code, 0, 3), 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
quickcheck! {
|
||||||
fn literals() {
|
#[test]
|
||||||
let code = r#"
|
fn literals(a: i32, b: i64, c: i32, d: i64) -> bool {
|
||||||
(module
|
let code = format!(r#"
|
||||||
(func (param i32) (param i32) (result i32)
|
(module
|
||||||
(i32.const 228)
|
(func (result i32)
|
||||||
)
|
(i32.const {})
|
||||||
)
|
)
|
||||||
"#;
|
(func (result i64)
|
||||||
|
(i64.const {})
|
||||||
|
)
|
||||||
|
(func (result f32)
|
||||||
|
(f32.const {})
|
||||||
|
)
|
||||||
|
(func (result f64)
|
||||||
|
(f64.const {})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
"#, a, b, c, d);
|
||||||
|
|
||||||
assert_eq!(execute_wat(code, 0, 0), 228);
|
let translated = translate_wat(&code);
|
||||||
|
|
||||||
|
assert_eq!(translated.execute_func::<(), i32>(0, ()), Ok(a));
|
||||||
|
assert_eq!(translated.execute_func::<(), i64>(1, ()), Ok(b));
|
||||||
|
assert_eq!(translated.execute_func::<(), f32>(2, ()), Ok(c as _));
|
||||||
|
assert_eq!(translated.execute_func::<(), f64>(3, ()), Ok(d as _));
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
quickcheck! {
|
||||||
|
#[test]
|
||||||
|
fn params(a: i32, b: i64, c: i32, d: i64) -> bool {
|
||||||
|
let code = r#"
|
||||||
|
(module
|
||||||
|
(func (param i32) (param i64) (param f32) (param f64) (result i32)
|
||||||
|
(get_local 0)
|
||||||
|
)
|
||||||
|
(func (param i32) (param i64) (param f32) (param f64) (result i64)
|
||||||
|
(get_local 1)
|
||||||
|
)
|
||||||
|
(func (param i32) (param i64) (param f32) (param f64) (result f32)
|
||||||
|
(get_local 2)
|
||||||
|
)
|
||||||
|
(func (param i32) (param i64) (param f32) (param f64) (result f64)
|
||||||
|
(get_local 3)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let c = c as f32;
|
||||||
|
let d = d as f64;
|
||||||
|
|
||||||
|
let translated = translate_wat(&code);
|
||||||
|
|
||||||
|
assert_eq!(translated.execute_func::<(i32, i64, f32, f64), i32>(0, (a, b, c, d)), Ok(a));
|
||||||
|
assert_eq!(translated.execute_func::<(i32, i64, f32, f64), i64>(1, (a, b, c, d)), Ok(b));
|
||||||
|
assert_eq!(translated.execute_func::<(i32, i64, f32, f64), f32>(2, (a, b, c, d)), Ok(c));
|
||||||
|
assert_eq!(translated.execute_func::<(i32, i64, f32, f64), f64>(3, (a, b, c, d)), Ok(d));
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn wrong_type() {
|
fn wrong_type() {
|
||||||
let code = r#"
|
let code = r#"
|
||||||
@@ -1094,7 +1145,7 @@ macro_rules! test_select {
|
|||||||
|
|
||||||
fn lit(cond: bool, then: $ty, else_: $ty) -> bool {
|
fn lit(cond: bool, then: $ty, else_: $ty) -> bool {
|
||||||
let icond: i32 = if cond { 1 } else { 0 };
|
let icond: i32 = if cond { 1 } else { 0 };
|
||||||
let translated = translate_wat(&format!("
|
let translated = translate_wat(&format!("
|
||||||
(module (func (param {ty}) (param {ty}) (result {ty})
|
(module (func (param {ty}) (param {ty}) (result {ty})
|
||||||
(select (get_local 0) (get_local 1) (i32.const {val}))))
|
(select (get_local 0) (get_local 1) (i32.const {val}))))
|
||||||
",
|
",
|
||||||
@@ -1130,6 +1181,13 @@ fn bench_fibonacci_run(b: &mut test::Bencher) {
|
|||||||
b.iter(|| module.execute_func::<_, u32>(0, (20,)));
|
b.iter(|| module.execute_func::<_, u32>(0, (20,)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_fibonacci_compile_run(b: &mut test::Bencher) {
|
||||||
|
let wasm = wabt::wat2wasm(FIBONACCI).unwrap();
|
||||||
|
|
||||||
|
b.iter(|| translate(&wasm).unwrap().execute_func::<_, u32>(0, (20,)));
|
||||||
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_fibonacci_baseline(b: &mut test::Bencher) {
|
fn bench_fibonacci_baseline(b: &mut test::Bencher) {
|
||||||
fn fib(n: i32) -> i32 {
|
fn fib(n: i32) -> i32 {
|
||||||
@@ -1142,3 +1200,349 @@ fn bench_fibonacci_baseline(b: &mut test::Bencher) {
|
|||||||
|
|
||||||
b.iter(|| test::black_box(fib(test::black_box(20))));
|
b.iter(|| test::black_box(fib(test::black_box(20))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn sieve() {
|
||||||
|
const CODE: &str = r#"
|
||||||
|
(module
|
||||||
|
(type $t0 (func (param i32 i32)))
|
||||||
|
(type $t1 (func (param i32 i32 i32) (result i32)))
|
||||||
|
(type $t2 (func (param i32 i32 i32)))
|
||||||
|
(type $t3 (func (param i32)))
|
||||||
|
(type $t4 (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32)))
|
||||||
|
(type $t5 (func (param i32 i32) (result i32)))
|
||||||
|
(func $optimized_sieve (export "optimized_sieve") (type $t0) (param $p0 i32) (param $p1 i32)
|
||||||
|
(local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (local $l11 i32) (local $l12 i32) (local $l13 i32) (local $l14 i32) (local $l15 i32) (local $l16 i32) (local $l17 i32) (local $l18 f64)
|
||||||
|
get_global $g0
|
||||||
|
i32.const 64
|
||||||
|
i32.sub
|
||||||
|
tee_local $l0
|
||||||
|
set_global $g0
|
||||||
|
i32.const 0
|
||||||
|
set_local $l1
|
||||||
|
get_local $l0
|
||||||
|
i32.const 0
|
||||||
|
i32.const 64
|
||||||
|
call $memset
|
||||||
|
set_local $l0
|
||||||
|
block $B0
|
||||||
|
block $B1
|
||||||
|
block $B2
|
||||||
|
block $B3
|
||||||
|
get_local $p1
|
||||||
|
i32.const 2
|
||||||
|
i32.gt_u
|
||||||
|
br_if $B3
|
||||||
|
i32.const -1
|
||||||
|
i32.const 0
|
||||||
|
get_local $p1
|
||||||
|
i32.const 2
|
||||||
|
i32.eq
|
||||||
|
select
|
||||||
|
set_local $p1
|
||||||
|
i32.const 0
|
||||||
|
set_local $l2
|
||||||
|
i32.const 0
|
||||||
|
set_local $l3
|
||||||
|
i32.const 0
|
||||||
|
set_local $l4
|
||||||
|
i32.const 0
|
||||||
|
set_local $l5
|
||||||
|
i32.const 0
|
||||||
|
set_local $l6
|
||||||
|
i32.const 0
|
||||||
|
set_local $l7
|
||||||
|
i32.const 0
|
||||||
|
set_local $l8
|
||||||
|
i32.const 0
|
||||||
|
set_local $l9
|
||||||
|
i32.const 0
|
||||||
|
set_local $l10
|
||||||
|
i32.const 0
|
||||||
|
set_local $l11
|
||||||
|
i32.const 0
|
||||||
|
set_local $l12
|
||||||
|
i32.const 0
|
||||||
|
set_local $l13
|
||||||
|
i32.const 0
|
||||||
|
set_local $l14
|
||||||
|
i32.const 0
|
||||||
|
set_local $l15
|
||||||
|
i32.const 0
|
||||||
|
set_local $l16
|
||||||
|
i32.const 0
|
||||||
|
set_local $l17
|
||||||
|
br $B2
|
||||||
|
end
|
||||||
|
get_local $p1
|
||||||
|
i32.const -3
|
||||||
|
i32.add
|
||||||
|
i32.const 1
|
||||||
|
i32.shr_u
|
||||||
|
set_local $l3
|
||||||
|
block $B4
|
||||||
|
block $B5
|
||||||
|
get_local $p1
|
||||||
|
f64.convert_u/i32
|
||||||
|
f64.sqrt
|
||||||
|
tee_local $l18
|
||||||
|
f64.const 0x1p+32 (;=4.29497e+09;)
|
||||||
|
f64.lt
|
||||||
|
get_local $l18
|
||||||
|
f64.const 0x0p+0 (;=0;)
|
||||||
|
f64.ge
|
||||||
|
i32.and
|
||||||
|
br_if $B5
|
||||||
|
i32.const 0
|
||||||
|
set_local $p1
|
||||||
|
br $B4
|
||||||
|
end
|
||||||
|
get_local $l18
|
||||||
|
i32.trunc_u/f64
|
||||||
|
set_local $p1
|
||||||
|
end
|
||||||
|
get_local $l3
|
||||||
|
i32.const 1
|
||||||
|
i32.add
|
||||||
|
set_local $l17
|
||||||
|
get_local $p1
|
||||||
|
i32.const -3
|
||||||
|
i32.add
|
||||||
|
i32.const 1
|
||||||
|
i32.shr_u
|
||||||
|
set_local $l5
|
||||||
|
i32.const 0
|
||||||
|
set_local $p1
|
||||||
|
loop $L6
|
||||||
|
get_local $p1
|
||||||
|
tee_local $l4
|
||||||
|
i32.const 5
|
||||||
|
i32.shr_u
|
||||||
|
set_local $p1
|
||||||
|
get_local $l4
|
||||||
|
i32.const 511
|
||||||
|
i32.gt_u
|
||||||
|
br_if $B0
|
||||||
|
block $B7
|
||||||
|
get_local $l0
|
||||||
|
get_local $p1
|
||||||
|
i32.const 2
|
||||||
|
i32.shl
|
||||||
|
i32.add
|
||||||
|
i32.load
|
||||||
|
i32.const 1
|
||||||
|
get_local $l4
|
||||||
|
i32.const 31
|
||||||
|
i32.and
|
||||||
|
i32.shl
|
||||||
|
i32.and
|
||||||
|
br_if $B7
|
||||||
|
get_local $l4
|
||||||
|
i32.const 1
|
||||||
|
i32.shl
|
||||||
|
i32.const 3
|
||||||
|
i32.add
|
||||||
|
tee_local $l2
|
||||||
|
get_local $l2
|
||||||
|
i32.mul
|
||||||
|
i32.const -3
|
||||||
|
i32.add
|
||||||
|
i32.const 1
|
||||||
|
i32.shr_u
|
||||||
|
tee_local $p1
|
||||||
|
get_local $l3
|
||||||
|
i32.gt_u
|
||||||
|
br_if $B7
|
||||||
|
loop $L8
|
||||||
|
get_local $p1
|
||||||
|
i32.const 5
|
||||||
|
i32.shr_u
|
||||||
|
set_local $l1
|
||||||
|
get_local $p1
|
||||||
|
i32.const 511
|
||||||
|
i32.gt_u
|
||||||
|
br_if $B1
|
||||||
|
get_local $l0
|
||||||
|
get_local $l1
|
||||||
|
i32.const 2
|
||||||
|
i32.shl
|
||||||
|
i32.add
|
||||||
|
tee_local $l1
|
||||||
|
get_local $l1
|
||||||
|
i32.load
|
||||||
|
i32.const 1
|
||||||
|
get_local $p1
|
||||||
|
i32.const 31
|
||||||
|
i32.and
|
||||||
|
i32.shl
|
||||||
|
i32.or
|
||||||
|
i32.store
|
||||||
|
get_local $p1
|
||||||
|
get_local $l2
|
||||||
|
i32.add
|
||||||
|
tee_local $p1
|
||||||
|
get_local $l3
|
||||||
|
i32.le_u
|
||||||
|
br_if $L8
|
||||||
|
end
|
||||||
|
end
|
||||||
|
get_local $l4
|
||||||
|
i32.const 1
|
||||||
|
i32.add
|
||||||
|
set_local $p1
|
||||||
|
get_local $l4
|
||||||
|
get_local $l5
|
||||||
|
i32.lt_u
|
||||||
|
br_if $L6
|
||||||
|
end
|
||||||
|
i32.const -1
|
||||||
|
set_local $p1
|
||||||
|
get_local $l0
|
||||||
|
i32.load offset=60
|
||||||
|
set_local $l1
|
||||||
|
get_local $l0
|
||||||
|
i32.load offset=56
|
||||||
|
set_local $l2
|
||||||
|
get_local $l0
|
||||||
|
i32.load offset=52
|
||||||
|
set_local $l3
|
||||||
|
get_local $l0
|
||||||
|
i32.load offset=48
|
||||||
|
set_local $l4
|
||||||
|
get_local $l0
|
||||||
|
i32.load offset=44
|
||||||
|
set_local $l5
|
||||||
|
get_local $l0
|
||||||
|
i32.load offset=40
|
||||||
|
set_local $l6
|
||||||
|
get_local $l0
|
||||||
|
i32.load offset=36
|
||||||
|
set_local $l7
|
||||||
|
get_local $l0
|
||||||
|
i32.load offset=32
|
||||||
|
set_local $l8
|
||||||
|
get_local $l0
|
||||||
|
i32.load offset=28
|
||||||
|
set_local $l9
|
||||||
|
get_local $l0
|
||||||
|
i32.load offset=24
|
||||||
|
set_local $l10
|
||||||
|
get_local $l0
|
||||||
|
i32.load offset=20
|
||||||
|
set_local $l11
|
||||||
|
get_local $l0
|
||||||
|
i32.load offset=16
|
||||||
|
set_local $l12
|
||||||
|
get_local $l0
|
||||||
|
i32.load offset=12
|
||||||
|
set_local $l13
|
||||||
|
get_local $l0
|
||||||
|
i32.load offset=8
|
||||||
|
set_local $l14
|
||||||
|
get_local $l0
|
||||||
|
i32.load offset=4
|
||||||
|
set_local $l15
|
||||||
|
get_local $l0
|
||||||
|
i32.load
|
||||||
|
set_local $l16
|
||||||
|
end
|
||||||
|
get_local $p0
|
||||||
|
get_local $l1
|
||||||
|
i32.store offset=68
|
||||||
|
get_local $p0
|
||||||
|
get_local $l2
|
||||||
|
i32.store offset=64
|
||||||
|
get_local $p0
|
||||||
|
get_local $l3
|
||||||
|
i32.store offset=60
|
||||||
|
get_local $p0
|
||||||
|
get_local $l4
|
||||||
|
i32.store offset=56
|
||||||
|
get_local $p0
|
||||||
|
get_local $l5
|
||||||
|
i32.store offset=52
|
||||||
|
get_local $p0
|
||||||
|
get_local $l6
|
||||||
|
i32.store offset=48
|
||||||
|
get_local $p0
|
||||||
|
get_local $l7
|
||||||
|
i32.store offset=44
|
||||||
|
get_local $p0
|
||||||
|
get_local $l8
|
||||||
|
i32.store offset=40
|
||||||
|
get_local $p0
|
||||||
|
get_local $l9
|
||||||
|
i32.store offset=36
|
||||||
|
get_local $p0
|
||||||
|
get_local $l10
|
||||||
|
i32.store offset=32
|
||||||
|
get_local $p0
|
||||||
|
get_local $l11
|
||||||
|
i32.store offset=28
|
||||||
|
get_local $p0
|
||||||
|
get_local $l12
|
||||||
|
i32.store offset=24
|
||||||
|
get_local $p0
|
||||||
|
get_local $l13
|
||||||
|
i32.store offset=20
|
||||||
|
get_local $p0
|
||||||
|
get_local $l14
|
||||||
|
i32.store offset=16
|
||||||
|
get_local $p0
|
||||||
|
get_local $l15
|
||||||
|
i32.store offset=12
|
||||||
|
get_local $p0
|
||||||
|
get_local $l16
|
||||||
|
i32.store offset=8
|
||||||
|
get_local $p0
|
||||||
|
get_local $l17
|
||||||
|
i32.store offset=4
|
||||||
|
get_local $p0
|
||||||
|
get_local $p1
|
||||||
|
i32.store
|
||||||
|
get_local $l0
|
||||||
|
i32.const 64
|
||||||
|
i32.add
|
||||||
|
set_global $g0
|
||||||
|
return
|
||||||
|
end
|
||||||
|
i32.const 1396
|
||||||
|
get_local $l1
|
||||||
|
i32.const 16
|
||||||
|
unreachable
|
||||||
|
end
|
||||||
|
i32.const 1380
|
||||||
|
get_local $p1
|
||||||
|
i32.const 16
|
||||||
|
unreachable)
|
||||||
|
(func $memset (type $t1) (param $p0 i32) (param $p1 i32) (param $p2 i32) (result i32)
|
||||||
|
(local $l0 i32)
|
||||||
|
block $B0
|
||||||
|
get_local $p2
|
||||||
|
i32.eqz
|
||||||
|
br_if $B0
|
||||||
|
get_local $p0
|
||||||
|
set_local $l0
|
||||||
|
loop $L1
|
||||||
|
get_local $l0
|
||||||
|
get_local $p1
|
||||||
|
i32.store8
|
||||||
|
get_local $l0
|
||||||
|
i32.const 1
|
||||||
|
i32.add
|
||||||
|
set_local $l0
|
||||||
|
get_local $p2
|
||||||
|
i32.const -1
|
||||||
|
i32.add
|
||||||
|
tee_local $p2
|
||||||
|
br_if $L1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
get_local $p0)
|
||||||
|
(memory $memory (export "memory") 17 17)
|
||||||
|
(global $g0 (mut i32) (i32.const 1050032)))
|
||||||
|
"#;
|
||||||
|
|
||||||
|
translate(&wabt::wat2wasm(CODE).unwrap()).unwrap();
|
||||||
|
}
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ pub fn code(
|
|||||||
&body,
|
&body,
|
||||||
);
|
);
|
||||||
|
|
||||||
if false {
|
if true {
|
||||||
let mut microwasm = vec![];
|
let mut microwasm = vec![];
|
||||||
|
|
||||||
let mut microwasm_conv = MicrowasmConv::new(
|
let mut microwasm_conv = MicrowasmConv::new(
|
||||||
|
|||||||
Reference in New Issue
Block a user