Use latest wasmparser instead of fork
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
|||||||
[submodule "wasmparser.rs"]
|
|
||||||
path = wasmparser.rs
|
|
||||||
url = git@github.com:Vurich/wasmparser.rs
|
|
||||||
@@ -13,7 +13,7 @@ edition = "2018"
|
|||||||
smallvec = "0.6"
|
smallvec = "0.6"
|
||||||
dynasm = "0.3"
|
dynasm = "0.3"
|
||||||
dynasmrt = "0.3"
|
dynasmrt = "0.3"
|
||||||
wasmparser = { path = "./wasmparser.rs" }
|
wasmparser = "0.29"
|
||||||
memoffset = "0.2"
|
memoffset = "0.2"
|
||||||
itertools = "0.8"
|
itertools = "0.8"
|
||||||
capstone = "0.5.0"
|
capstone = "0.5.0"
|
||||||
|
|||||||
120
src/backend.rs
120
src/backend.rs
@@ -1,5 +1,5 @@
|
|||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::microwasm::{BrTarget, SignlessType, Type, Value, F32, F64, I32, I64};
|
use crate::microwasm::{BrTarget, Ieee32, Ieee64, SignlessType, Type, Value, F32, F64, I32, I64};
|
||||||
use crate::module::ModuleContext;
|
use crate::module::ModuleContext;
|
||||||
use cranelift_codegen::{binemit, ir};
|
use cranelift_codegen::{binemit, ir};
|
||||||
use dynasm::dynasm;
|
use dynasm::dynasm;
|
||||||
@@ -459,11 +459,11 @@ impl ValueLocation {
|
|||||||
self.immediate().and_then(Value::as_i64)
|
self.immediate().and_then(Value::as_i64)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn imm_f32(self) -> Option<wasmparser::Ieee32> {
|
fn imm_f32(self) -> Option<Ieee32> {
|
||||||
self.immediate().and_then(Value::as_f32)
|
self.immediate().and_then(Value::as_f32)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn imm_f64(self) -> Option<wasmparser::Ieee64> {
|
fn imm_f64(self) -> Option<Ieee64> {
|
||||||
self.immediate().and_then(Value::as_f64)
|
self.immediate().and_then(Value::as_f64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1257,7 +1257,7 @@ macro_rules! cmp_float {
|
|||||||
(@helper $cmp_instr:ident, $ty:ty, $imm_fn:ident, $self:expr, $left:expr, $right:expr, $instr:ident, $const_fallback:expr) => {{
|
(@helper $cmp_instr:ident, $ty:ty, $imm_fn:ident, $self:expr, $left:expr, $right:expr, $instr:ident, $const_fallback:expr) => {{
|
||||||
let (left, right, this) = ($left, $right, $self);
|
let (left, right, this) = ($left, $right, $self);
|
||||||
if let (Some(left), Some(right)) = (left.$imm_fn(), right.$imm_fn()) {
|
if let (Some(left), Some(right)) = (left.$imm_fn(), right.$imm_fn()) {
|
||||||
if $const_fallback(<$ty>::from_bits(left.bits()), <$ty>::from_bits(right.bits())) {
|
if $const_fallback(<$ty>::from_bits(left.to_bits()), <$ty>::from_bits(right.to_bits())) {
|
||||||
ValueLocation::Immediate(1i32.into())
|
ValueLocation::Immediate(1i32.into())
|
||||||
} else {
|
} else {
|
||||||
ValueLocation::Immediate(0i32.into())
|
ValueLocation::Immediate(0i32.into())
|
||||||
@@ -1410,8 +1410,8 @@ macro_rules! binop_f32 {
|
|||||||
binop!(
|
binop!(
|
||||||
$name,
|
$name,
|
||||||
$instr,
|
$instr,
|
||||||
|a: wasmparser::Ieee32, b: wasmparser::Ieee32| wasmparser::Ieee32(
|
|a: Ieee32, b: Ieee32| Ieee32::from_bits(
|
||||||
$const_fallback(f32::from_bits(a.bits()), f32::from_bits(b.bits())).to_bits()
|
$const_fallback(f32::from_bits(a.to_bits()), f32::from_bits(b.to_bits())).to_bits()
|
||||||
),
|
),
|
||||||
Rx,
|
Rx,
|
||||||
rx,
|
rx,
|
||||||
@@ -1427,8 +1427,8 @@ macro_rules! commutative_binop_f32 {
|
|||||||
commutative_binop!(
|
commutative_binop!(
|
||||||
$name,
|
$name,
|
||||||
$instr,
|
$instr,
|
||||||
|a: wasmparser::Ieee32, b: wasmparser::Ieee32| wasmparser::Ieee32(
|
|a: Ieee32, b: Ieee32| Ieee32::from_bits(
|
||||||
$const_fallback(f32::from_bits(a.bits()), f32::from_bits(b.bits())).to_bits()
|
$const_fallback(f32::from_bits(a.to_bits()), f32::from_bits(b.to_bits())).to_bits()
|
||||||
),
|
),
|
||||||
Rx,
|
Rx,
|
||||||
rx,
|
rx,
|
||||||
@@ -1444,8 +1444,8 @@ macro_rules! binop_f64 {
|
|||||||
binop!(
|
binop!(
|
||||||
$name,
|
$name,
|
||||||
$instr,
|
$instr,
|
||||||
|a: wasmparser::Ieee64, b: wasmparser::Ieee64| wasmparser::Ieee64(
|
|a: Ieee64, b: Ieee64| Ieee64::from_bits(
|
||||||
$const_fallback(f64::from_bits(a.bits()), f64::from_bits(b.bits())).to_bits()
|
$const_fallback(f64::from_bits(a.to_bits()), f64::from_bits(b.to_bits())).to_bits()
|
||||||
),
|
),
|
||||||
Rx,
|
Rx,
|
||||||
rx,
|
rx,
|
||||||
@@ -1461,8 +1461,8 @@ macro_rules! commutative_binop_f64 {
|
|||||||
commutative_binop!(
|
commutative_binop!(
|
||||||
$name,
|
$name,
|
||||||
$instr,
|
$instr,
|
||||||
|a: wasmparser::Ieee64, b: wasmparser::Ieee64| wasmparser::Ieee64(
|
|a: Ieee64, b: Ieee64| Ieee64::from_bits(
|
||||||
$const_fallback(f64::from_bits(a.bits()), f64::from_bits(b.bits())).to_bits()
|
$const_fallback(f64::from_bits(a.to_bits()), f64::from_bits(b.to_bits())).to_bits()
|
||||||
),
|
),
|
||||||
Rx,
|
Rx,
|
||||||
rx,
|
rx,
|
||||||
@@ -1998,13 +1998,13 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
f32_eq,
|
f32_eq,
|
||||||
cmpeqss,
|
cmpeqss,
|
||||||
as_f32,
|
as_f32,
|
||||||
|a: wasmparser::Ieee32, b: wasmparser::Ieee32| f32::from_bits(a.0) == f32::from_bits(b.0)
|
|a: Ieee32, b: Ieee32| f32::from_bits(a.to_bits()) == f32::from_bits(b.to_bits())
|
||||||
);
|
);
|
||||||
eq_float!(
|
eq_float!(
|
||||||
f32_ne,
|
f32_ne,
|
||||||
cmpneqss,
|
cmpneqss,
|
||||||
as_f32,
|
as_f32,
|
||||||
|a: wasmparser::Ieee32, b: wasmparser::Ieee32| f32::from_bits(a.0) != f32::from_bits(b.0)
|
|a: Ieee32, b: Ieee32| f32::from_bits(a.to_bits()) != f32::from_bits(b.to_bits())
|
||||||
);
|
);
|
||||||
|
|
||||||
cmp_f64!(f64_gt, f64_lt, seta, |a, b| a > b);
|
cmp_f64!(f64_gt, f64_lt, seta, |a, b| a > b);
|
||||||
@@ -2013,13 +2013,13 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
f64_eq,
|
f64_eq,
|
||||||
cmpeqsd,
|
cmpeqsd,
|
||||||
as_f64,
|
as_f64,
|
||||||
|a: wasmparser::Ieee64, b: wasmparser::Ieee64| f64::from_bits(a.0) == f64::from_bits(b.0)
|
|a: Ieee64, b: Ieee64| f64::from_bits(a.to_bits()) == f64::from_bits(b.to_bits())
|
||||||
);
|
);
|
||||||
eq_float!(
|
eq_float!(
|
||||||
f64_ne,
|
f64_ne,
|
||||||
cmpneqsd,
|
cmpneqsd,
|
||||||
as_f64,
|
as_f64,
|
||||||
|a: wasmparser::Ieee64, b: wasmparser::Ieee64| f64::from_bits(a.0) != f64::from_bits(b.0)
|
|a: Ieee64, b: Ieee64| f64::from_bits(a.to_bits()) != f64::from_bits(b.to_bits())
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: Should we do this logic in `eq` and just have this delegate to `eq`?
|
// TODO: Should we do this logic in `eq` and just have this delegate to `eq`?
|
||||||
@@ -2866,7 +2866,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out = if let Some(i) = val.imm_f32() {
|
let out = if let Some(i) = val.imm_f32() {
|
||||||
ValueLocation::Immediate(
|
ValueLocation::Immediate(
|
||||||
wasmparser::Ieee32((-f32::from_bits(i.bits())).to_bits()).into(),
|
Ieee32::from_bits((-f32::from_bits(i.to_bits())).to_bits()).into(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let reg = self.into_temp_reg(GPRType::Rx, val);
|
let reg = self.into_temp_reg(GPRType::Rx, val);
|
||||||
@@ -2887,7 +2887,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out = if let Some(i) = val.imm_f64() {
|
let out = if let Some(i) = val.imm_f64() {
|
||||||
ValueLocation::Immediate(
|
ValueLocation::Immediate(
|
||||||
wasmparser::Ieee64((-f64::from_bits(i.bits())).to_bits()).into(),
|
Ieee64::from_bits((-f64::from_bits(i.to_bits())).to_bits()).into(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let reg = self.into_temp_reg(GPRType::Rx, val);
|
let reg = self.into_temp_reg(GPRType::Rx, val);
|
||||||
@@ -2908,7 +2908,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out = if let Some(i) = val.imm_f32() {
|
let out = if let Some(i) = val.imm_f32() {
|
||||||
ValueLocation::Immediate(
|
ValueLocation::Immediate(
|
||||||
wasmparser::Ieee32(f32::from_bits(i.bits()).abs().to_bits()).into(),
|
Ieee32::from_bits(f32::from_bits(i.to_bits()).abs().to_bits()).into(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let reg = self.into_temp_reg(GPRType::Rx, val);
|
let reg = self.into_temp_reg(GPRType::Rx, val);
|
||||||
@@ -2929,7 +2929,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out = if let Some(i) = val.imm_f64() {
|
let out = if let Some(i) = val.imm_f64() {
|
||||||
ValueLocation::Immediate(
|
ValueLocation::Immediate(
|
||||||
wasmparser::Ieee64(f64::from_bits(i.bits()).abs().to_bits()).into(),
|
Ieee64::from_bits(f64::from_bits(i.to_bits()).abs().to_bits()).into(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let reg = self.into_temp_reg(GPRType::Rx, val);
|
let reg = self.into_temp_reg(GPRType::Rx, val);
|
||||||
@@ -2950,7 +2950,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out = if let Some(i) = val.imm_f32() {
|
let out = if let Some(i) = val.imm_f32() {
|
||||||
ValueLocation::Immediate(
|
ValueLocation::Immediate(
|
||||||
wasmparser::Ieee32(f32::from_bits(i.bits()).sqrt().to_bits()).into(),
|
Ieee32::from_bits(f32::from_bits(i.to_bits()).sqrt().to_bits()).into(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let reg = self.into_temp_reg(GPRType::Rx, val);
|
let reg = self.into_temp_reg(GPRType::Rx, val);
|
||||||
@@ -2970,7 +2970,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out = if let Some(i) = val.imm_f64() {
|
let out = if let Some(i) = val.imm_f64() {
|
||||||
ValueLocation::Immediate(
|
ValueLocation::Immediate(
|
||||||
wasmparser::Ieee64(f64::from_bits(i.bits()).sqrt().to_bits()).into(),
|
Ieee64::from_bits(f64::from_bits(i.to_bits()).sqrt().to_bits()).into(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let reg = self.into_temp_reg(GPRType::Rx, val);
|
let reg = self.into_temp_reg(GPRType::Rx, val);
|
||||||
@@ -2991,7 +2991,9 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out = if let (Some(left), Some(right)) = (left.imm_f32(), right.imm_f32()) {
|
let out = if let (Some(left), Some(right)) = (left.imm_f32(), right.imm_f32()) {
|
||||||
ValueLocation::Immediate(
|
ValueLocation::Immediate(
|
||||||
wasmparser::Ieee32((left.bits() & REST_MASK_F32) | (right.bits() & SIGN_MASK_F32))
|
Ieee32::from_bits(
|
||||||
|
(left.to_bits() & REST_MASK_F32) | (right.to_bits() & SIGN_MASK_F32),
|
||||||
|
)
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -3020,7 +3022,9 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out = if let (Some(left), Some(right)) = (left.imm_f64(), right.imm_f64()) {
|
let out = if let (Some(left), Some(right)) = (left.imm_f64(), right.imm_f64()) {
|
||||||
ValueLocation::Immediate(
|
ValueLocation::Immediate(
|
||||||
wasmparser::Ieee64((left.bits() & REST_MASK_F64) | (right.bits() & SIGN_MASK_F64))
|
Ieee64::from_bits(
|
||||||
|
(left.to_bits() & REST_MASK_F64) | (right.to_bits() & SIGN_MASK_F64),
|
||||||
|
)
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -3134,7 +3138,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
f32,
|
f32,
|
||||||
f64,
|
f64,
|
||||||
as_f32,
|
as_f32,
|
||||||
|a: wasmparser::Ieee32| wasmparser::Ieee64((f32::from_bits(a.bits()) as f64).to_bits())
|
|a: Ieee32| Ieee64::from_bits((f32::from_bits(a.to_bits()) as f64).to_bits())
|
||||||
);
|
);
|
||||||
conversion!(
|
conversion!(
|
||||||
f32_from_f64,
|
f32_from_f64,
|
||||||
@@ -3146,14 +3150,14 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
f64,
|
f64,
|
||||||
f32,
|
f32,
|
||||||
as_f64,
|
as_f64,
|
||||||
|a: wasmparser::Ieee64| wasmparser::Ieee32((f64::from_bits(a.bits()) as f32).to_bits())
|
|a: Ieee64| Ieee32::from_bits((f64::from_bits(a.to_bits()) as f32).to_bits())
|
||||||
);
|
);
|
||||||
pub fn i32_truncate_f32_s(&mut self) {
|
pub fn i32_truncate_f32_s(&mut self) {
|
||||||
let mut val = self.pop();
|
let mut val = self.pop();
|
||||||
|
|
||||||
let out_val = match val {
|
let out_val = match val {
|
||||||
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
||||||
(f32::from_bits(imm.as_f32().unwrap().bits()) as i32).into(),
|
(f32::from_bits(imm.as_f32().unwrap().to_bits()) as i32).into(),
|
||||||
),
|
),
|
||||||
other => {
|
other => {
|
||||||
let reg = self.into_reg(F32, other);
|
let reg = self.into_reg(F32, other);
|
||||||
@@ -3192,7 +3196,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out_val = match val {
|
let out_val = match val {
|
||||||
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
||||||
(f32::from_bits(imm.as_f32().unwrap().bits()) as i32).into(),
|
(f32::from_bits(imm.as_f32().unwrap().to_bits()) as i32).into(),
|
||||||
),
|
),
|
||||||
other => {
|
other => {
|
||||||
let reg = self.into_temp_reg(F32, other);
|
let reg = self.into_temp_reg(F32, other);
|
||||||
@@ -3234,7 +3238,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out_val = match val {
|
let out_val = match val {
|
||||||
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
||||||
(f64::from_bits(imm.as_f64().unwrap().bits()) as i32).into(),
|
(f64::from_bits(imm.as_f64().unwrap().to_bits()) as i32).into(),
|
||||||
),
|
),
|
||||||
other => {
|
other => {
|
||||||
let reg = self.into_reg(F32, other);
|
let reg = self.into_reg(F32, other);
|
||||||
@@ -3274,7 +3278,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out_val = match val {
|
let out_val = match val {
|
||||||
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
||||||
(f32::from_bits(imm.as_f32().unwrap().bits()) as i32).into(),
|
(f32::from_bits(imm.as_f32().unwrap().to_bits()) as i32).into(),
|
||||||
),
|
),
|
||||||
other => {
|
other => {
|
||||||
let reg = self.into_temp_reg(F32, other);
|
let reg = self.into_temp_reg(F32, other);
|
||||||
@@ -3322,7 +3326,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
i32,
|
i32,
|
||||||
f32,
|
f32,
|
||||||
as_i32,
|
as_i32,
|
||||||
|a| wasmparser::Ieee32((a as f32).to_bits())
|
|a| Ieee32::from_bits((a as f32).to_bits())
|
||||||
);
|
);
|
||||||
conversion!(
|
conversion!(
|
||||||
f64_convert_from_i32_s,
|
f64_convert_from_i32_s,
|
||||||
@@ -3334,7 +3338,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
i32,
|
i32,
|
||||||
f64,
|
f64,
|
||||||
as_i32,
|
as_i32,
|
||||||
|a| wasmparser::Ieee64((a as f64).to_bits())
|
|a| Ieee64::from_bits((a as f64).to_bits())
|
||||||
);
|
);
|
||||||
conversion!(
|
conversion!(
|
||||||
f32_convert_from_i64_s,
|
f32_convert_from_i64_s,
|
||||||
@@ -3346,7 +3350,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
i64,
|
i64,
|
||||||
f32,
|
f32,
|
||||||
as_i32,
|
as_i32,
|
||||||
|a| wasmparser::Ieee32((a as f32).to_bits())
|
|a| Ieee32::from_bits((a as f32).to_bits())
|
||||||
);
|
);
|
||||||
conversion!(
|
conversion!(
|
||||||
f64_convert_from_i64_s,
|
f64_convert_from_i64_s,
|
||||||
@@ -3358,7 +3362,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
i64,
|
i64,
|
||||||
f64,
|
f64,
|
||||||
as_i32,
|
as_i32,
|
||||||
|a| wasmparser::Ieee64((a as f64).to_bits())
|
|a| Ieee64::from_bits((a as f64).to_bits())
|
||||||
);
|
);
|
||||||
|
|
||||||
pub fn i64_truncate_f32_s(&mut self) {
|
pub fn i64_truncate_f32_s(&mut self) {
|
||||||
@@ -3366,7 +3370,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out_val = match val {
|
let out_val = match val {
|
||||||
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
||||||
(f32::from_bits(imm.as_f32().unwrap().bits()) as i32).into(),
|
(f32::from_bits(imm.as_f32().unwrap().to_bits()) as i32).into(),
|
||||||
),
|
),
|
||||||
other => {
|
other => {
|
||||||
let reg = self.into_temp_reg(F32, other);
|
let reg = self.into_temp_reg(F32, other);
|
||||||
@@ -3405,7 +3409,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out_val = match val {
|
let out_val = match val {
|
||||||
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
||||||
(f64::from_bits(imm.as_f64().unwrap().bits()) as i32).into(),
|
(f64::from_bits(imm.as_f64().unwrap().to_bits()) as i32).into(),
|
||||||
),
|
),
|
||||||
other => {
|
other => {
|
||||||
let reg = self.into_reg(F32, other);
|
let reg = self.into_reg(F32, other);
|
||||||
@@ -3445,7 +3449,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out_val = match val {
|
let out_val = match val {
|
||||||
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
||||||
(f32::from_bits(imm.as_f32().unwrap().bits()) as u64).into(),
|
(f32::from_bits(imm.as_f32().unwrap().to_bits()) as u64).into(),
|
||||||
),
|
),
|
||||||
_ => {
|
_ => {
|
||||||
let reg = self.into_reg(F32, val);
|
let reg = self.into_reg(F32, val);
|
||||||
@@ -3487,7 +3491,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out_val = match val {
|
let out_val = match val {
|
||||||
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
||||||
(f64::from_bits(imm.as_f64().unwrap().bits()) as u64).into(),
|
(f64::from_bits(imm.as_f64().unwrap().to_bits()) as u64).into(),
|
||||||
),
|
),
|
||||||
_ => {
|
_ => {
|
||||||
let reg = self.into_reg(F64, val);
|
let reg = self.into_reg(F64, val);
|
||||||
@@ -3530,7 +3534,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out_val = match val {
|
let out_val = match val {
|
||||||
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
||||||
wasmparser::Ieee32((imm.as_i32().unwrap() as u32 as f32).to_bits()).into(),
|
Ieee32::from_bits((imm.as_i32().unwrap() as u32 as f32).to_bits()).into(),
|
||||||
),
|
),
|
||||||
_ => {
|
_ => {
|
||||||
let reg = self.into_reg(I32, val);
|
let reg = self.into_reg(I32, val);
|
||||||
@@ -3557,7 +3561,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out_val = match val {
|
let out_val = match val {
|
||||||
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
||||||
wasmparser::Ieee64((imm.as_i32().unwrap() as u32 as f64).to_bits()).into(),
|
Ieee64::from_bits((imm.as_i32().unwrap() as u32 as f64).to_bits()).into(),
|
||||||
),
|
),
|
||||||
_ => {
|
_ => {
|
||||||
let reg = self.into_reg(I32, val);
|
let reg = self.into_reg(I32, val);
|
||||||
@@ -3584,7 +3588,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out_val = match val {
|
let out_val = match val {
|
||||||
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
||||||
wasmparser::Ieee32((imm.as_i32().unwrap() as u64 as f32).to_bits()).into(),
|
Ieee32::from_bits((imm.as_i32().unwrap() as u64 as f32).to_bits()).into(),
|
||||||
),
|
),
|
||||||
_ => {
|
_ => {
|
||||||
let reg = self.into_reg(I64, val);
|
let reg = self.into_reg(I64, val);
|
||||||
@@ -3624,7 +3628,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out_val = match val {
|
let out_val = match val {
|
||||||
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
||||||
wasmparser::Ieee64((imm.as_i64().unwrap() as u64 as f64).to_bits()).into(),
|
Ieee64::from_bits((imm.as_i64().unwrap() as u64 as f64).to_bits()).into(),
|
||||||
),
|
),
|
||||||
_ => {
|
_ => {
|
||||||
let reg = self.into_reg(I64, val);
|
let reg = self.into_reg(I64, val);
|
||||||
@@ -3664,7 +3668,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out = match val {
|
let out = match val {
|
||||||
ValueLocation::Immediate(imm) => {
|
ValueLocation::Immediate(imm) => {
|
||||||
ValueLocation::Immediate(imm.as_f32().unwrap().bits().into())
|
ValueLocation::Immediate(imm.as_f32().unwrap().to_bits().into())
|
||||||
}
|
}
|
||||||
val => val,
|
val => val,
|
||||||
};
|
};
|
||||||
@@ -3677,7 +3681,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out = match val {
|
let out = match val {
|
||||||
ValueLocation::Immediate(imm) => {
|
ValueLocation::Immediate(imm) => {
|
||||||
ValueLocation::Immediate(imm.as_f64().unwrap().bits().into())
|
ValueLocation::Immediate(imm.as_f64().unwrap().to_bits().into())
|
||||||
}
|
}
|
||||||
val => val,
|
val => val,
|
||||||
};
|
};
|
||||||
@@ -3690,7 +3694,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out = match val {
|
let out = match val {
|
||||||
ValueLocation::Immediate(imm) => {
|
ValueLocation::Immediate(imm) => {
|
||||||
ValueLocation::Immediate(wasmparser::Ieee32(imm.as_i32().unwrap() as _).into())
|
ValueLocation::Immediate(Ieee32::from_bits(imm.as_i32().unwrap() as _).into())
|
||||||
}
|
}
|
||||||
val => val,
|
val => val,
|
||||||
};
|
};
|
||||||
@@ -3703,7 +3707,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
|
|
||||||
let out = match val {
|
let out = match val {
|
||||||
ValueLocation::Immediate(imm) => {
|
ValueLocation::Immediate(imm) => {
|
||||||
ValueLocation::Immediate(wasmparser::Ieee64(imm.as_i64().unwrap() as _).into())
|
ValueLocation::Immediate(Ieee64::from_bits(imm.as_i64().unwrap() as _).into())
|
||||||
}
|
}
|
||||||
val => val,
|
val => val,
|
||||||
};
|
};
|
||||||
@@ -3736,8 +3740,10 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
addss,
|
addss,
|
||||||
orps,
|
orps,
|
||||||
as_f32,
|
as_f32,
|
||||||
|a: wasmparser::Ieee32, b: wasmparser::Ieee32| wasmparser::Ieee32(
|
|a: Ieee32, b: Ieee32| Ieee32::from_bits(
|
||||||
f32::from_bits(a.0).min(f32::from_bits(b.0)).to_bits()
|
f32::from_bits(a.to_bits())
|
||||||
|
.min(f32::from_bits(b.to_bits()))
|
||||||
|
.to_bits()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
minmax_float!(
|
minmax_float!(
|
||||||
@@ -3747,8 +3753,10 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
addss,
|
addss,
|
||||||
andps,
|
andps,
|
||||||
as_f32,
|
as_f32,
|
||||||
|a: wasmparser::Ieee32, b: wasmparser::Ieee32| wasmparser::Ieee32(
|
|a: Ieee32, b: Ieee32| Ieee32::from_bits(
|
||||||
f32::from_bits(a.0).max(f32::from_bits(b.0)).to_bits()
|
f32::from_bits(a.to_bits())
|
||||||
|
.max(f32::from_bits(b.to_bits()))
|
||||||
|
.to_bits()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
binop_f32!(f32_sub, subss, |a, b| a - b);
|
binop_f32!(f32_sub, subss, |a, b| a - b);
|
||||||
@@ -3799,8 +3807,10 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
addsd,
|
addsd,
|
||||||
orpd,
|
orpd,
|
||||||
as_f64,
|
as_f64,
|
||||||
|a: wasmparser::Ieee64, b: wasmparser::Ieee64| wasmparser::Ieee64(
|
|a: Ieee64, b: Ieee64| Ieee64::from_bits(
|
||||||
f64::from_bits(a.0).min(f64::from_bits(b.0)).to_bits()
|
f64::from_bits(a.to_bits())
|
||||||
|
.min(f64::from_bits(b.to_bits()))
|
||||||
|
.to_bits()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
minmax_float!(
|
minmax_float!(
|
||||||
@@ -3810,8 +3820,10 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
addsd,
|
addsd,
|
||||||
andpd,
|
andpd,
|
||||||
as_f64,
|
as_f64,
|
||||||
|a: wasmparser::Ieee64, b: wasmparser::Ieee64| wasmparser::Ieee64(
|
|a: Ieee64, b: Ieee64| Ieee64::from_bits(
|
||||||
f64::from_bits(a.0).max(f64::from_bits(b.0)).to_bits()
|
f64::from_bits(a.to_bits())
|
||||||
|
.max(f64::from_bits(b.to_bits()))
|
||||||
|
.to_bits()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
binop_f64!(f64_sub, subsd, |a, b| a - b);
|
binop_f64!(f64_sub, subsd, |a, b| a - b);
|
||||||
|
|||||||
143
src/microwasm.rs
143
src/microwasm.rs
@@ -7,7 +7,8 @@ use std::{
|
|||||||
ops::RangeInclusive,
|
ops::RangeInclusive,
|
||||||
};
|
};
|
||||||
use wasmparser::{
|
use wasmparser::{
|
||||||
FunctionBody, Ieee32, Ieee64, MemoryImmediate, Operator as WasmOperator, OperatorsReader,
|
FunctionBody, Ieee32 as WasmIeee32, Ieee64 as WasmIeee64, MemoryImmediate as WasmMemoryImmediate, Operator as WasmOperator,
|
||||||
|
OperatorsReader,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn dis<L>(
|
pub fn dis<L>(
|
||||||
@@ -49,8 +50,8 @@ impl fmt::Display for Value {
|
|||||||
match self {
|
match self {
|
||||||
Value::I32(v) => write!(f, "{}i32", v),
|
Value::I32(v) => write!(f, "{}i32", v),
|
||||||
Value::I64(v) => write!(f, "{}i64", v),
|
Value::I64(v) => write!(f, "{}i64", v),
|
||||||
Value::F32(v) => write!(f, "{}f32", f32::from_bits(v.bits())),
|
Value::F32(v) => write!(f, "{}f32", f32::from_bits(v.to_bits())),
|
||||||
Value::F64(v) => write!(f, "{}f64", f64::from_bits(v.bits())),
|
Value::F64(v) => write!(f, "{}f64", f64::from_bits(v.to_bits())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -304,13 +305,6 @@ pub enum NameTag {
|
|||||||
|
|
||||||
pub type WasmLabel = (u32, NameTag);
|
pub type WasmLabel = (u32, NameTag);
|
||||||
|
|
||||||
trait Label {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This is for Wasm blocks - we should have an increasing ID for each block that we hit.
|
|
||||||
impl Label for (u32, NameTag) {}
|
|
||||||
|
|
||||||
type OperatorFromWasm = Operator<WasmLabel>;
|
type OperatorFromWasm = Operator<WasmLabel>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
@@ -388,6 +382,58 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||||
|
pub struct Ieee32(u32);
|
||||||
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||||
|
pub struct Ieee64(u64);
|
||||||
|
|
||||||
|
impl Ieee32 {
|
||||||
|
pub fn to_bits(self) -> u32 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_bits(other: u32) -> Self {
|
||||||
|
Ieee32(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<WasmIeee32> for Ieee32 {
|
||||||
|
fn from(other: WasmIeee32) -> Self {
|
||||||
|
Self::from_bits(other.bits())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ieee64 {
|
||||||
|
pub fn to_bits(self) -> u64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_bits(other: u64) -> Self {
|
||||||
|
Ieee64(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<WasmIeee64> for Ieee64 {
|
||||||
|
fn from(other: WasmIeee64) -> Self {
|
||||||
|
Self::from_bits(other.bits())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
|
pub struct MemoryImmediate {
|
||||||
|
pub flags: u32,
|
||||||
|
pub offset: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<WasmMemoryImmediate> for MemoryImmediate {
|
||||||
|
fn from(other: WasmMemoryImmediate) -> Self {
|
||||||
|
MemoryImmediate {
|
||||||
|
flags: other.flags,
|
||||||
|
offset: other.offset,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Explicit VmCtx?
|
// TODO: Explicit VmCtx?
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Operator<Label> {
|
pub enum Operator<Label> {
|
||||||
@@ -1750,79 +1796,105 @@ where
|
|||||||
smallvec![Operator::SetGlobal(global_index)]
|
smallvec![Operator::SetGlobal(global_index)]
|
||||||
}
|
}
|
||||||
|
|
||||||
WasmOperator::I32Load { memarg } => smallvec![Operator::Load { ty: I32, memarg }],
|
WasmOperator::I32Load { memarg } => smallvec![Operator::Load {
|
||||||
WasmOperator::I64Load { memarg } => smallvec![Operator::Load { ty: I64, memarg }],
|
ty: I32,
|
||||||
WasmOperator::F32Load { memarg } => smallvec![Operator::Load { ty: F32, memarg }],
|
memarg: memarg.into()
|
||||||
WasmOperator::F64Load { memarg } => smallvec![Operator::Load { ty: F64, memarg }],
|
}],
|
||||||
|
WasmOperator::I64Load { memarg } => smallvec![Operator::Load {
|
||||||
|
ty: I64,
|
||||||
|
memarg: memarg.into()
|
||||||
|
}],
|
||||||
|
WasmOperator::F32Load { memarg } => smallvec![Operator::Load {
|
||||||
|
ty: F32,
|
||||||
|
memarg: memarg.into()
|
||||||
|
}],
|
||||||
|
WasmOperator::F64Load { memarg } => smallvec![Operator::Load {
|
||||||
|
ty: F64,
|
||||||
|
memarg: memarg.into()
|
||||||
|
}],
|
||||||
WasmOperator::I32Load8S { memarg } => smallvec![Operator::Load8 {
|
WasmOperator::I32Load8S { memarg } => smallvec![Operator::Load8 {
|
||||||
ty: sint::I32,
|
ty: sint::I32,
|
||||||
memarg,
|
memarg: memarg.into(),
|
||||||
}],
|
}],
|
||||||
WasmOperator::I32Load8U { memarg } => smallvec![Operator::Load8 {
|
WasmOperator::I32Load8U { memarg } => smallvec![Operator::Load8 {
|
||||||
ty: sint::U32,
|
ty: sint::U32,
|
||||||
memarg,
|
memarg: memarg.into(),
|
||||||
}],
|
}],
|
||||||
WasmOperator::I32Load16S { memarg } => smallvec![Operator::Load16 {
|
WasmOperator::I32Load16S { memarg } => smallvec![Operator::Load16 {
|
||||||
ty: sint::I32,
|
ty: sint::I32,
|
||||||
memarg,
|
memarg: memarg.into(),
|
||||||
}],
|
}],
|
||||||
WasmOperator::I32Load16U { memarg } => smallvec![Operator::Load16 {
|
WasmOperator::I32Load16U { memarg } => smallvec![Operator::Load16 {
|
||||||
ty: sint::U32,
|
ty: sint::U32,
|
||||||
memarg,
|
memarg: memarg.into(),
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Load8S { memarg } => smallvec![Operator::Load8 {
|
WasmOperator::I64Load8S { memarg } => smallvec![Operator::Load8 {
|
||||||
ty: sint::I64,
|
ty: sint::I64,
|
||||||
memarg,
|
memarg: memarg.into(),
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Load8U { memarg } => smallvec![Operator::Load8 {
|
WasmOperator::I64Load8U { memarg } => smallvec![Operator::Load8 {
|
||||||
ty: sint::U64,
|
ty: sint::U64,
|
||||||
memarg,
|
memarg: memarg.into(),
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Load16S { memarg } => smallvec![Operator::Load16 {
|
WasmOperator::I64Load16S { memarg } => smallvec![Operator::Load16 {
|
||||||
ty: sint::I64,
|
ty: sint::I64,
|
||||||
memarg,
|
memarg: memarg.into(),
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Load16U { memarg } => smallvec![Operator::Load16 {
|
WasmOperator::I64Load16U { memarg } => smallvec![Operator::Load16 {
|
||||||
ty: sint::U64,
|
ty: sint::U64,
|
||||||
memarg,
|
memarg: memarg.into(),
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Load32S { memarg } => smallvec![Operator::Load32 {
|
WasmOperator::I64Load32S { memarg } => smallvec![Operator::Load32 {
|
||||||
sign: Signedness::Signed,
|
sign: Signedness::Signed,
|
||||||
memarg,
|
memarg: memarg.into(),
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Load32U { memarg } => smallvec![Operator::Load32 {
|
WasmOperator::I64Load32U { memarg } => smallvec![Operator::Load32 {
|
||||||
sign: Signedness::Unsigned,
|
sign: Signedness::Unsigned,
|
||||||
memarg,
|
memarg: memarg.into(),
|
||||||
}],
|
}],
|
||||||
|
|
||||||
WasmOperator::I32Store { memarg } => smallvec![Operator::Store { ty: I32, memarg }],
|
WasmOperator::I32Store { memarg } => smallvec![Operator::Store {
|
||||||
WasmOperator::I64Store { memarg } => smallvec![Operator::Store { ty: I64, memarg }],
|
ty: I32,
|
||||||
WasmOperator::F32Store { memarg } => smallvec![Operator::Store { ty: F32, memarg }],
|
memarg: memarg.into()
|
||||||
WasmOperator::F64Store { memarg } => smallvec![Operator::Store { ty: F64, memarg }],
|
}],
|
||||||
|
WasmOperator::I64Store { memarg } => smallvec![Operator::Store {
|
||||||
|
ty: I64,
|
||||||
|
memarg: memarg.into()
|
||||||
|
}],
|
||||||
|
WasmOperator::F32Store { memarg } => smallvec![Operator::Store {
|
||||||
|
ty: F32,
|
||||||
|
memarg: memarg.into()
|
||||||
|
}],
|
||||||
|
WasmOperator::F64Store { memarg } => smallvec![Operator::Store {
|
||||||
|
ty: F64,
|
||||||
|
memarg: memarg.into()
|
||||||
|
}],
|
||||||
|
|
||||||
WasmOperator::I32Store8 { memarg } => smallvec![Operator::Store8 {
|
WasmOperator::I32Store8 { memarg } => smallvec![Operator::Store8 {
|
||||||
ty: Size::_32,
|
ty: Size::_32,
|
||||||
memarg,
|
memarg: memarg.into(),
|
||||||
}],
|
}],
|
||||||
WasmOperator::I32Store16 { memarg } => smallvec![Operator::Store16 {
|
WasmOperator::I32Store16 { memarg } => smallvec![Operator::Store16 {
|
||||||
ty: Size::_32,
|
ty: Size::_32,
|
||||||
memarg,
|
memarg: memarg.into(),
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Store8 { memarg } => smallvec![Operator::Store8 {
|
WasmOperator::I64Store8 { memarg } => smallvec![Operator::Store8 {
|
||||||
ty: Size::_64,
|
ty: Size::_64,
|
||||||
memarg,
|
memarg: memarg.into(),
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Store16 { memarg } => smallvec![Operator::Store16 {
|
WasmOperator::I64Store16 { memarg } => smallvec![Operator::Store16 {
|
||||||
ty: Size::_64,
|
ty: Size::_64,
|
||||||
memarg,
|
memarg: memarg.into(),
|
||||||
|
}],
|
||||||
|
WasmOperator::I64Store32 { memarg } => smallvec![Operator::Store32 {
|
||||||
|
memarg: memarg.into()
|
||||||
}],
|
}],
|
||||||
WasmOperator::I64Store32 { memarg } => smallvec![Operator::Store32 { memarg }],
|
|
||||||
WasmOperator::MemorySize { reserved } => smallvec![Operator::MemorySize { reserved }],
|
WasmOperator::MemorySize { reserved } => smallvec![Operator::MemorySize { reserved }],
|
||||||
WasmOperator::MemoryGrow { reserved } => smallvec![Operator::MemoryGrow { reserved }],
|
WasmOperator::MemoryGrow { reserved } => smallvec![Operator::MemoryGrow { reserved }],
|
||||||
WasmOperator::I32Const { value } => smallvec![Operator::Const(Value::I32(value))],
|
WasmOperator::I32Const { value } => smallvec![Operator::Const(Value::I32(value))],
|
||||||
WasmOperator::I64Const { value } => smallvec![Operator::Const(Value::I64(value))],
|
WasmOperator::I64Const { value } => smallvec![Operator::Const(Value::I64(value))],
|
||||||
WasmOperator::F32Const { value } => smallvec![Operator::Const(Value::F32(value))],
|
WasmOperator::F32Const { value } => smallvec![Operator::Const(Value::F32(value.into()))],
|
||||||
WasmOperator::F64Const { value } => smallvec![Operator::Const(Value::F64(value))],
|
WasmOperator::F64Const { value } => smallvec![Operator::Const(Value::F64(value.into()))],
|
||||||
WasmOperator::RefNull => unimplemented!("{:?}", op),
|
WasmOperator::RefNull => unimplemented!("{:?}", op),
|
||||||
WasmOperator::RefIsNull => unimplemented!("{:?}", op),
|
WasmOperator::RefIsNull => unimplemented!("{:?}", op),
|
||||||
WasmOperator::I32Eqz => smallvec![Operator::Eqz(Size::_32)],
|
WasmOperator::I32Eqz => smallvec![Operator::Eqz(Size::_32)],
|
||||||
@@ -2098,3 +2170,4 @@ where
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
155
src/module.rs
155
src/module.rs
@@ -6,12 +6,8 @@ use cranelift_codegen::{
|
|||||||
ir::{self, AbiParam, Signature as CraneliftSignature},
|
ir::{self, AbiParam, Signature as CraneliftSignature},
|
||||||
isa,
|
isa,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{convert::TryInto, mem};
|
||||||
convert::TryInto,
|
use wasmparser::{FuncType, MemoryType, ModuleReader, SectionCode, Type};
|
||||||
hash::{Hash, Hasher},
|
|
||||||
mem,
|
|
||||||
};
|
|
||||||
use wasmparser::{FuncType, MemoryType, ModuleReader, SectionCode, TableType, Type};
|
|
||||||
|
|
||||||
pub trait AsValueType {
|
pub trait AsValueType {
|
||||||
const TYPE: Type;
|
const TYPE: Type;
|
||||||
@@ -105,70 +101,18 @@ pub struct TranslatedModule {
|
|||||||
ctx: SimpleContext,
|
ctx: SimpleContext,
|
||||||
// TODO: Should we wrap this in a `Mutex` so that calling functions from multiple
|
// TODO: Should we wrap this in a `Mutex` so that calling functions from multiple
|
||||||
// threads doesn't cause data races?
|
// threads doesn't cause data races?
|
||||||
table: Option<(TableType, Vec<u32>)>,
|
|
||||||
memory: Option<MemoryType>,
|
memory: Option<MemoryType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn quickhash<H: Hash>(h: H) -> u64 {
|
|
||||||
let mut hasher = std::collections::hash_map::DefaultHasher::new();
|
|
||||||
h.hash(&mut hasher);
|
|
||||||
hasher.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TranslatedModule {
|
impl TranslatedModule {
|
||||||
pub fn instantiate(mut self) -> ExecutableModule {
|
pub fn instantiate(self) -> ExecutableModule {
|
||||||
let table = {
|
|
||||||
let code_section = self
|
|
||||||
.translated_code_section
|
|
||||||
.as_ref()
|
|
||||||
.expect("We don't currently support a table section without a code section");
|
|
||||||
let ctx = &self.ctx;
|
|
||||||
|
|
||||||
self.table
|
|
||||||
.as_mut()
|
|
||||||
.map(|&mut (_, ref mut idxs)| {
|
|
||||||
let initial = idxs
|
|
||||||
.iter()
|
|
||||||
.map(|i| {
|
|
||||||
let start = code_section.func_start(*i as _);
|
|
||||||
let ty = ctx.func_type(*i);
|
|
||||||
|
|
||||||
RuntimeFunc {
|
|
||||||
func_start: start,
|
|
||||||
sig_hash: quickhash(ty),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let out = BoxSlice::from(initial.into_boxed_slice());
|
|
||||||
out
|
|
||||||
})
|
|
||||||
.unwrap_or(BoxSlice {
|
|
||||||
ptr: std::ptr::NonNull::dangling().as_ptr(),
|
|
||||||
len: 0,
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let mem_size = self.memory.map(|m| m.limits.initial).unwrap_or(0) as usize;
|
let mem_size = self.memory.map(|m| m.limits.initial).unwrap_or(0) as usize;
|
||||||
let mem: BoxSlice<_> = vec![0u8; mem_size * WASM_PAGE_SIZE]
|
let mem: BoxSlice<_> = vec![0u8; mem_size * WASM_PAGE_SIZE]
|
||||||
.into_boxed_slice()
|
.into_boxed_slice()
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let ctx = if mem.len > 0 || table.len > 0 {
|
let ctx = if mem.len > 0 {
|
||||||
let hashes = self.ctx.types.iter().map(quickhash).collect::<Vec<_>>();
|
Some(Box::new(VmCtx { mem }) as Box<VmCtx>)
|
||||||
|
|
||||||
// Hardcoded maximum number of hashes supported for now - we will eventually port all our
|
|
||||||
// tests over to wasmtime which will make this obsolete so implementing this properly is
|
|
||||||
// unnecessary.
|
|
||||||
let mut out = [0; 64];
|
|
||||||
|
|
||||||
// This will panic if `hashes.len() > 64`
|
|
||||||
out[..hashes.len()].copy_from_slice(&hashes[..]);
|
|
||||||
|
|
||||||
Some(Box::new(GVmCtx {
|
|
||||||
table,
|
|
||||||
mem,
|
|
||||||
hashes: out,
|
|
||||||
}) as Box<VmCtx>)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@@ -248,26 +192,6 @@ impl ExecutableModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type FuncRef = *const u8;
|
|
||||||
|
|
||||||
pub struct RuntimeFunc {
|
|
||||||
sig_hash: u64,
|
|
||||||
func_start: FuncRef,
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Send for RuntimeFunc {}
|
|
||||||
unsafe impl Sync for RuntimeFunc {}
|
|
||||||
|
|
||||||
impl RuntimeFunc {
|
|
||||||
pub fn offset_of_sig_hash() -> usize {
|
|
||||||
offset_of!(Self, sig_hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn offset_of_func_start() -> usize {
|
|
||||||
offset_of!(Self, func_start)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct BoxSlice<T> {
|
struct BoxSlice<T> {
|
||||||
len: usize,
|
len: usize,
|
||||||
ptr: *mut T,
|
ptr: *mut T,
|
||||||
@@ -293,44 +217,22 @@ impl<T> Drop for BoxSlice<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type VmCtx = GVmCtx<[u64]>;
|
pub struct VmCtx {
|
||||||
|
|
||||||
pub struct GVmCtx<T: ?Sized> {
|
|
||||||
table: BoxSlice<RuntimeFunc>,
|
|
||||||
mem: BoxSlice<u8>,
|
mem: BoxSlice<u8>,
|
||||||
hashes: T,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized> GVmCtx<T> {
|
impl VmCtx {
|
||||||
pub fn offset_of_memory_ptr() -> u32 {
|
pub fn offset_of_memory_ptr() -> u32 {
|
||||||
offset_of!(GVmCtx<[u64; 0]>, mem.ptr)
|
offset_of!(VmCtx, mem.ptr)
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("Offset exceeded size of u32")
|
.expect("Offset exceeded size of u32")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset_of_memory_len() -> u32 {
|
pub fn offset_of_memory_len() -> u32 {
|
||||||
offset_of!(GVmCtx<[u64; 0]>, mem.len)
|
offset_of!(VmCtx, mem.len)
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("Offset exceeded size of u32")
|
.expect("Offset exceeded size of u32")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset_of_funcs_ptr() -> u8 {
|
|
||||||
offset_of!(GVmCtx<[u64; 0]>, table.ptr)
|
|
||||||
.try_into()
|
|
||||||
.expect("Offset exceeded size of u8")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn offset_of_funcs_len() -> u8 {
|
|
||||||
offset_of!(GVmCtx<[u64; 0]>, table.len)
|
|
||||||
.try_into()
|
|
||||||
.expect("Offset exceeded size of u8")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn offset_of_hashes() -> u8 {
|
|
||||||
offset_of!(GVmCtx<[u64; 0]>, hashes)
|
|
||||||
.try_into()
|
|
||||||
.expect("Offset exceeded size of u8")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
@@ -545,19 +447,16 @@ impl ModuleContext for SimpleContext {
|
|||||||
VmCtx::offset_of_memory_len()
|
VmCtx::offset_of_memory_len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vmctx_vmtable_definition(&self, defined_table_index: u32) -> u32 {
|
fn vmctx_vmtable_definition(&self, _defined_table_index: u32) -> u32 {
|
||||||
assert_eq!(defined_table_index, 0);
|
unimplemented!()
|
||||||
VmCtx::offset_of_funcs_ptr() as _
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vmctx_vmtable_definition_base(&self, defined_table_index: u32) -> u32 {
|
fn vmctx_vmtable_definition_base(&self, _defined_table_index: u32) -> u32 {
|
||||||
assert_eq!(defined_table_index, 0);
|
unimplemented!()
|
||||||
VmCtx::offset_of_funcs_ptr() as _
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vmctx_vmtable_definition_current_elements(&self, defined_table_index: u32) -> u32 {
|
fn vmctx_vmtable_definition_current_elements(&self, _defined_table_index: u32) -> u32 {
|
||||||
assert_eq!(defined_table_index, 0);
|
unimplemented!()
|
||||||
VmCtx::offset_of_funcs_len() as _
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vmtable_definition_base(&self) -> u8 {
|
fn vmtable_definition_base(&self) -> u8 {
|
||||||
@@ -573,19 +472,19 @@ impl ModuleContext for SimpleContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn vmcaller_checked_anyfunc_type_index(&self) -> u8 {
|
fn vmcaller_checked_anyfunc_type_index(&self) -> u8 {
|
||||||
RuntimeFunc::offset_of_sig_hash() as _
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vmcaller_checked_anyfunc_func_ptr(&self) -> u8 {
|
fn vmcaller_checked_anyfunc_func_ptr(&self) -> u8 {
|
||||||
RuntimeFunc::offset_of_func_start() as _
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size_of_vmcaller_checked_anyfunc(&self) -> u8 {
|
fn size_of_vmcaller_checked_anyfunc(&self) -> u8 {
|
||||||
std::mem::size_of::<RuntimeFunc>() as _
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vmctx_vmshared_signature_id(&self, signature_idx: u32) -> u32 {
|
fn vmctx_vmshared_signature_id(&self, _signature_idx: u32) -> u32 {
|
||||||
VmCtx::offset_of_hashes() as u32 + signature_idx * std::mem::size_of::<u64>() as u32
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: type of a global
|
// TODO: type of a global
|
||||||
@@ -599,7 +498,6 @@ pub fn translate(data: &[u8]) -> Result<ExecutableModule, Error> {
|
|||||||
pub fn translate_only(data: &[u8]) -> Result<TranslatedModule, Error> {
|
pub fn translate_only(data: &[u8]) -> Result<TranslatedModule, Error> {
|
||||||
let mut reader = ModuleReader::new(data)?;
|
let mut reader = ModuleReader::new(data)?;
|
||||||
let mut output = TranslatedModule::default();
|
let mut output = TranslatedModule::default();
|
||||||
let mut table = None;
|
|
||||||
|
|
||||||
reader.skip_custom_sections()?;
|
reader.skip_custom_sections()?;
|
||||||
if reader.eof() {
|
if reader.eof() {
|
||||||
@@ -642,11 +540,7 @@ pub fn translate_only(data: &[u8]) -> Result<TranslatedModule, Error> {
|
|||||||
|
|
||||||
if let SectionCode::Table = section.code {
|
if let SectionCode::Table = section.code {
|
||||||
let tables = section.get_table_section_reader()?;
|
let tables = section.get_table_section_reader()?;
|
||||||
let mut tables = translate_sections::table(tables)?;
|
translate_sections::table(tables)?;
|
||||||
|
|
||||||
assert!(tables.len() <= 1);
|
|
||||||
|
|
||||||
table = tables.drain(..).next();
|
|
||||||
|
|
||||||
reader.skip_custom_sections()?;
|
reader.skip_custom_sections()?;
|
||||||
if reader.eof() {
|
if reader.eof() {
|
||||||
@@ -712,12 +606,7 @@ pub fn translate_only(data: &[u8]) -> Result<TranslatedModule, Error> {
|
|||||||
|
|
||||||
if let SectionCode::Element = section.code {
|
if let SectionCode::Element = section.code {
|
||||||
let elements = section.get_element_section_reader()?;
|
let elements = section.get_element_section_reader()?;
|
||||||
let elements = translate_sections::element(elements)?;
|
translate_sections::element(elements)?;
|
||||||
|
|
||||||
output.table = Some((
|
|
||||||
table.expect("Element section with no table section"),
|
|
||||||
elements,
|
|
||||||
));
|
|
||||||
|
|
||||||
reader.skip_custom_sections()?;
|
reader.skip_custom_sections()?;
|
||||||
if reader.eof() {
|
if reader.eof() {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use cranelift_codegen::{binemit, ir};
|
|||||||
use wasmparser::{
|
use wasmparser::{
|
||||||
CodeSectionReader, DataSectionReader, ElementSectionReader, ExportSectionReader, FuncType,
|
CodeSectionReader, DataSectionReader, ElementSectionReader, ExportSectionReader, FuncType,
|
||||||
FunctionSectionReader, GlobalSectionReader, ImportSectionReader, MemorySectionReader,
|
FunctionSectionReader, GlobalSectionReader, ImportSectionReader, MemorySectionReader,
|
||||||
MemoryType, Operator, TableSectionReader, TableType, TypeSectionReader,
|
MemoryType, TableSectionReader, TableType, TypeSectionReader,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Parses the Type section of the wasm module.
|
/// Parses the Type section of the wasm module.
|
||||||
@@ -69,37 +69,12 @@ pub fn start(_index: u32) -> Result<(), Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the Element section of the wasm module.
|
/// Parses the Element section of the wasm module.
|
||||||
pub fn element(elements: ElementSectionReader) -> Result<Vec<u32>, Error> {
|
pub fn element(elements: ElementSectionReader) -> Result<(), Error> {
|
||||||
let mut out = Vec::new();
|
|
||||||
|
|
||||||
for entry in elements {
|
for entry in elements {
|
||||||
let entry = entry?;
|
entry?;
|
||||||
|
|
||||||
assert_eq!(entry.table_index, 0);
|
|
||||||
let offset = {
|
|
||||||
let mut reader = entry.init_expr.get_operators_reader();
|
|
||||||
let out = match reader.read() {
|
|
||||||
Ok(Operator::I32Const { value }) => value,
|
|
||||||
_ => panic!("We only support i32.const table init expressions right now"),
|
|
||||||
};
|
|
||||||
|
|
||||||
//reader.ensure_end()?;
|
|
||||||
|
|
||||||
out
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_eq!(offset, out.len() as i32);
|
|
||||||
|
|
||||||
let elements = entry
|
|
||||||
.items
|
|
||||||
.get_items_reader()?
|
|
||||||
.into_iter()
|
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
|
||||||
|
|
||||||
out.extend(elements);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(out)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UnimplementedRelocSink;
|
struct UnimplementedRelocSink;
|
||||||
|
|||||||
Submodule wasmparser.rs deleted from e8bc42b377
Reference in New Issue
Block a user