Compare commits
No commits in common. "8fff4913c0dcd18db52a6d6aad3728c114d5d9a2" and "332a4216e6b57d348b456e30688673673cf4b8ca" have entirely different histories.
8fff4913c0
...
332a4216e6
|
@ -7,8 +7,8 @@ license = "Apache-2.0 WITH LLVM-exception"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmparser = "0.212"
|
wasmparser = "0.202"
|
||||||
wasm-encoder = "0.212"
|
wasm-encoder = "0.202"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
structopt = "0.3"
|
structopt = "0.3"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
@ -26,7 +26,6 @@ indexmap = "2.2.2"
|
||||||
stacker = "0.1.15"
|
stacker = "0.1.15"
|
||||||
wasm-smith = { version = "0.202", optional = true }
|
wasm-smith = { version = "0.202", optional = true }
|
||||||
paste = "1.0.15"
|
paste = "1.0.15"
|
||||||
serde = { version = "1.0.204", features = ["derive"] }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
|
|
@ -8,7 +8,6 @@ use anyhow::Result;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use wasm_encoder::CustomSection;
|
use wasm_encoder::CustomSection;
|
||||||
use wasm_encoder::Encode;
|
|
||||||
|
|
||||||
pub mod stackify;
|
pub mod stackify;
|
||||||
use stackify::{Context as StackifyContext, WasmBlock};
|
use stackify::{Context as StackifyContext, WasmBlock};
|
||||||
|
@ -211,8 +210,8 @@ impl<'a> WasmFuncBackend<'a> {
|
||||||
self.lower_value(value, func);
|
self.lower_value(value, func);
|
||||||
}
|
}
|
||||||
func.instruction(&wasm_encoder::Instruction::ReturnCallIndirect {
|
func.instruction(&wasm_encoder::Instruction::ReturnCallIndirect {
|
||||||
type_index: sig.index() as u32,
|
ty: sig.index() as u32,
|
||||||
table_index: table.index() as u32,
|
table: table.index() as u32,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
WasmBlock::ReturnCallRef { sig, values } => {
|
WasmBlock::ReturnCallRef { sig, values } => {
|
||||||
|
@ -300,8 +299,8 @@ impl<'a> WasmFuncBackend<'a> {
|
||||||
sig_index,
|
sig_index,
|
||||||
table_index,
|
table_index,
|
||||||
} => Some(wasm_encoder::Instruction::CallIndirect {
|
} => Some(wasm_encoder::Instruction::CallIndirect {
|
||||||
type_index: sig_index.index() as u32,
|
ty: sig_index.index() as u32,
|
||||||
table_index: table_index.index() as u32,
|
table: table_index.index() as u32,
|
||||||
}),
|
}),
|
||||||
Operator::Select => Some(wasm_encoder::Instruction::Select),
|
Operator::Select => Some(wasm_encoder::Instruction::Select),
|
||||||
Operator::TypedSelect { ty } => Some(wasm_encoder::Instruction::TypedSelect(
|
Operator::TypedSelect { ty } => Some(wasm_encoder::Instruction::TypedSelect(
|
||||||
|
@ -1142,11 +1141,9 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<wasm_encoder::Module> {
|
||||||
minimum: table
|
minimum: table
|
||||||
.func_elements
|
.func_elements
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|elts| elts.len() as u64)
|
.map(|elts| elts.len() as u32)
|
||||||
.unwrap_or(table.initial),
|
.unwrap_or(table.initial),
|
||||||
maximum: table.max,
|
maximum: table.max,
|
||||||
table64: table.table64,
|
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
&ImportKind::Global(global) => {
|
&ImportKind::Global(global) => {
|
||||||
|
@ -1155,7 +1152,6 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<wasm_encoder::Module> {
|
||||||
wasm_encoder::EntityType::Global(wasm_encoder::GlobalType {
|
wasm_encoder::EntityType::Global(wasm_encoder::GlobalType {
|
||||||
val_type: wasm_encoder::ValType::from(global.ty),
|
val_type: wasm_encoder::ValType::from(global.ty),
|
||||||
mutable: global.mutable,
|
mutable: global.mutable,
|
||||||
shared: false,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
&ImportKind::Memory(mem) => {
|
&ImportKind::Memory(mem) => {
|
||||||
|
@ -1166,7 +1162,6 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<wasm_encoder::Module> {
|
||||||
shared: mem.shared,
|
shared: mem.shared,
|
||||||
minimum: mem.initial_pages as u64,
|
minimum: mem.initial_pages as u64,
|
||||||
maximum: mem.maximum_pages.map(|val| val as u64),
|
maximum: mem.maximum_pages.map(|val| val as u64),
|
||||||
page_size_log2: None,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1197,9 +1192,8 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<wasm_encoder::Module> {
|
||||||
.func_elements
|
.func_elements
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|elt| elt.len())
|
.map(|elt| elt.len())
|
||||||
.unwrap_or(0) as u64,
|
.unwrap_or(0) as u32,
|
||||||
maximum: table_data.max,
|
maximum: table_data.max,
|
||||||
table64: table_data.table64,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
into_mod.section(&tables);
|
into_mod.section(&tables);
|
||||||
|
@ -1211,7 +1205,6 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<wasm_encoder::Module> {
|
||||||
maximum: mem_data.maximum_pages.map(|val| val as u64),
|
maximum: mem_data.maximum_pages.map(|val| val as u64),
|
||||||
memory64: mem_data.memory64,
|
memory64: mem_data.memory64,
|
||||||
shared: mem_data.shared,
|
shared: mem_data.shared,
|
||||||
page_size_log2: None,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
into_mod.section(&memories);
|
into_mod.section(&memories);
|
||||||
|
@ -1222,7 +1215,6 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<wasm_encoder::Module> {
|
||||||
wasm_encoder::GlobalType {
|
wasm_encoder::GlobalType {
|
||||||
val_type: wasm_encoder::ValType::from(global_data.ty),
|
val_type: wasm_encoder::ValType::from(global_data.ty),
|
||||||
mutable: global_data.mutable,
|
mutable: global_data.mutable,
|
||||||
shared: false,
|
|
||||||
},
|
},
|
||||||
&const_init(global_data.ty, global_data.value),
|
&const_init(global_data.ty, global_data.value),
|
||||||
);
|
);
|
||||||
|
@ -1304,6 +1296,11 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<wasm_encoder::Module> {
|
||||||
|
|
||||||
let mut code = wasm_encoder::CodeSection::new();
|
let mut code = wasm_encoder::CodeSection::new();
|
||||||
|
|
||||||
|
enum FuncOrRawBytes<'a> {
|
||||||
|
Raw(&'a [u8]),
|
||||||
|
Func(Cow<'a, wasm_encoder::Function>),
|
||||||
|
}
|
||||||
|
|
||||||
let bodies = module
|
let bodies = module
|
||||||
.funcs
|
.funcs
|
||||||
.entries()
|
.entries()
|
||||||
|
@ -1314,14 +1311,16 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<wasm_encoder::Module> {
|
||||||
match func_decl {
|
match func_decl {
|
||||||
FuncDecl::Lazy(_, _name, reader) => {
|
FuncDecl::Lazy(_, _name, reader) => {
|
||||||
let data = &module.orig_bytes[reader.range()];
|
let data = &module.orig_bytes[reader.range()];
|
||||||
Ok(Cow::Borrowed(data))
|
Ok(FuncOrRawBytes::Raw(data))
|
||||||
|
}
|
||||||
|
FuncDecl::Compiled(_, _name, encoder) => {
|
||||||
|
Ok(FuncOrRawBytes::Func(Cow::Borrowed(encoder)))
|
||||||
}
|
}
|
||||||
FuncDecl::Compiled(_, _name, bytes) => Ok(Cow::Borrowed(&bytes[..])),
|
|
||||||
FuncDecl::Body(_, name, body) => {
|
FuncDecl::Body(_, name, body) => {
|
||||||
log::debug!("Compiling {} \"{}\"", func, name);
|
log::debug!("Compiling {} \"{}\"", func, name);
|
||||||
WasmFuncBackend::new(body)?
|
WasmFuncBackend::new(body)?
|
||||||
.compile()
|
.compile()
|
||||||
.map(|func| Cow::Owned(func.into_raw_body()))
|
.map(|func| FuncOrRawBytes::Func(Cow::Owned(func)))
|
||||||
}
|
}
|
||||||
FuncDecl::Import(_, _) => unreachable!("Should have skipped imports"),
|
FuncDecl::Import(_, _) => unreachable!("Should have skipped imports"),
|
||||||
FuncDecl::None => panic!("FuncDecl::None at compilation time"),
|
FuncDecl::None => panic!("FuncDecl::None at compilation time"),
|
||||||
|
@ -1330,7 +1329,14 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<wasm_encoder::Module> {
|
||||||
.collect::<Result<Vec<_>>>()?;
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
|
||||||
for body in bodies {
|
for body in bodies {
|
||||||
code.raw(&body);
|
match body {
|
||||||
|
FuncOrRawBytes::Raw(bytes) => {
|
||||||
|
code.raw(bytes);
|
||||||
|
}
|
||||||
|
FuncOrRawBytes::Func(func) => {
|
||||||
|
code.function(&*func);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
into_mod.section(&code);
|
into_mod.section(&code);
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ fn main() -> Result<()> {
|
||||||
let mut ctx = InterpContext::new(&module)?;
|
let mut ctx = InterpContext::new(&module)?;
|
||||||
debug!("Calling start function");
|
debug!("Calling start function");
|
||||||
if let Some(start) = module.start_func {
|
if let Some(start) = module.start_func {
|
||||||
ctx.call(&mut module, start, &[]).ok().unwrap();
|
ctx.call(&module, start, &[]).ok().unwrap();
|
||||||
}
|
}
|
||||||
// Find a function called `_start`, if any.
|
// Find a function called `_start`, if any.
|
||||||
if let Some(waffle::Export {
|
if let Some(waffle::Export {
|
||||||
|
@ -133,7 +133,7 @@ fn main() -> Result<()> {
|
||||||
}) = module.exports.iter().find(|e| &e.name == "_start")
|
}) = module.exports.iter().find(|e| &e.name == "_start")
|
||||||
{
|
{
|
||||||
debug!("Calling _start");
|
debug!("Calling _start");
|
||||||
ctx.call(&mut module, *func, &[]).ok().unwrap();
|
ctx.call(&module, *func, &[]).ok().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub trait EntityRef: Clone + Copy + PartialEq + Eq + PartialOrd + Ord + Hash {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! declare_entity {
|
macro_rules! declare_entity {
|
||||||
($name:tt, $prefix:tt) => {
|
($name:tt, $prefix:tt) => {
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct $name(u32);
|
pub struct $name(u32);
|
||||||
|
|
||||||
impl $crate::entity::EntityRef for $name {
|
impl $crate::entity::EntityRef for $name {
|
||||||
|
@ -73,7 +73,7 @@ macro_rules! declare_entity {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct EntityVec<Idx: EntityRef, T: Clone + Debug>(Vec<T>, PhantomData<Idx>);
|
pub struct EntityVec<Idx: EntityRef, T: Clone + Debug>(Vec<T>, PhantomData<Idx>);
|
||||||
|
|
||||||
impl<Idx: EntityRef, T: Clone + Debug> std::default::Default for EntityVec<Idx, T> {
|
impl<Idx: EntityRef, T: Clone + Debug> std::default::Default for EntityVec<Idx, T> {
|
||||||
|
@ -151,7 +151,7 @@ impl<Idx: EntityRef, T: Clone + Debug> IndexMut<Idx> for EntityVec<Idx, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct PerEntity<Idx: EntityRef, T: Clone + Debug + Default>(Vec<T>, PhantomData<Idx>, T);
|
pub struct PerEntity<Idx: EntityRef, T: Clone + Debug + Default>(Vec<T>, PhantomData<Idx>, T);
|
||||||
|
|
||||||
impl<Idx: EntityRef, T: Clone + Debug + Default> Index<Idx> for PerEntity<Idx, T> {
|
impl<Idx: EntityRef, T: Clone + Debug + Default> Index<Idx> for PerEntity<Idx, T> {
|
||||||
|
|
126
src/frontend.rs
126
src/frontend.rs
|
@ -13,7 +13,9 @@ use anyhow::{bail, Result};
|
||||||
use fxhash::{FxHashMap, FxHashSet};
|
use fxhash::{FxHashMap, FxHashSet};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use wasmparser::{BlockType, DataKind, ExternalKind, KnownCustom, Name, Parser, Payload, TypeRef};
|
use wasmparser::{
|
||||||
|
BlockType, DataKind, ExternalKind, Name, NameSectionReader, Parser, Payload, TypeRef,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
pub struct FrontendOptions {
|
pub struct FrontendOptions {
|
||||||
|
@ -135,7 +137,6 @@ fn handle_payload<'a>(
|
||||||
ty.element_type.into(),
|
ty.element_type.into(),
|
||||||
ty.initial,
|
ty.initial,
|
||||||
ty.maximum,
|
ty.maximum,
|
||||||
ty.table64,
|
|
||||||
);
|
);
|
||||||
ImportKind::Table(table)
|
ImportKind::Table(table)
|
||||||
}
|
}
|
||||||
|
@ -183,7 +184,6 @@ fn handle_payload<'a>(
|
||||||
table.ty.element_type.into(),
|
table.ty.element_type.into(),
|
||||||
table.ty.initial,
|
table.ty.initial,
|
||||||
table.ty.maximum,
|
table.ty.maximum,
|
||||||
table.ty.table64,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,68 +255,72 @@ fn handle_payload<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Payload::CustomSection(reader) => match reader.as_known() {
|
Payload::CustomSection(reader) if reader.name() == "name" => {
|
||||||
KnownCustom::Name(name_reader) => {
|
let name_reader = NameSectionReader::new(reader.data(), reader.data_offset());
|
||||||
for subsection in name_reader {
|
for subsection in name_reader {
|
||||||
let subsection = subsection?;
|
let subsection = subsection?;
|
||||||
match subsection {
|
match subsection {
|
||||||
Name::Function(names) => {
|
Name::Function(names) => {
|
||||||
for name in names {
|
for name in names {
|
||||||
let name = name?;
|
let name = name?;
|
||||||
module.funcs[Func::new(name.index as usize)].set_name(name.name);
|
module.funcs[Func::new(name.index as usize)].set_name(name.name);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KnownCustom::Unknown => {
|
}
|
||||||
if reader.name() == ".debug_info" {
|
Payload::CustomSection(reader) if reader.name() == ".debug_info" => {
|
||||||
dwarf.debug_info = gimli::DebugInfo::new(reader.data(), gimli::LittleEndian);
|
dwarf.debug_info = gimli::DebugInfo::new(reader.data(), gimli::LittleEndian);
|
||||||
} else if reader.name() == ".debug_abbrev" {
|
}
|
||||||
dwarf.debug_abbrev =
|
Payload::CustomSection(reader) if reader.name() == ".debug_abbrev" => {
|
||||||
gimli::DebugAbbrev::new(reader.data(), gimli::LittleEndian);
|
dwarf.debug_abbrev = gimli::DebugAbbrev::new(reader.data(), gimli::LittleEndian);
|
||||||
} else if reader.name() == ".debug_addr" {
|
}
|
||||||
dwarf.debug_addr = gimli::DebugAddr::from(gimli::EndianSlice::new(
|
Payload::CustomSection(reader) if reader.name() == ".debug_addr" => {
|
||||||
reader.data(),
|
dwarf.debug_addr =
|
||||||
gimli::LittleEndian,
|
gimli::DebugAddr::from(gimli::EndianSlice::new(reader.data(), gimli::LittleEndian));
|
||||||
));
|
}
|
||||||
} else if reader.name() == ".debug_aranges" {
|
Payload::CustomSection(reader) if reader.name() == ".debug_aranges" => {
|
||||||
dwarf.debug_aranges =
|
dwarf.debug_aranges = gimli::DebugAranges::new(reader.data(), gimli::LittleEndian);
|
||||||
gimli::DebugAranges::new(reader.data(), gimli::LittleEndian);
|
}
|
||||||
} else if reader.name() == ".debug_line" {
|
Payload::CustomSection(reader) if reader.name() == ".debug_line" => {
|
||||||
dwarf.debug_line = gimli::DebugLine::new(reader.data(), gimli::LittleEndian);
|
dwarf.debug_line = gimli::DebugLine::new(reader.data(), gimli::LittleEndian);
|
||||||
} else if reader.name() == ".debug_line_str" {
|
}
|
||||||
dwarf.debug_line_str =
|
Payload::CustomSection(reader) if reader.name() == ".debug_line_str" => {
|
||||||
gimli::DebugLineStr::new(reader.data(), gimli::LittleEndian);
|
dwarf.debug_line_str = gimli::DebugLineStr::new(reader.data(), gimli::LittleEndian);
|
||||||
} else if reader.name() == ".debug_str" {
|
}
|
||||||
dwarf.debug_str = gimli::DebugStr::new(reader.data(), gimli::LittleEndian);
|
Payload::CustomSection(reader) if reader.name() == ".debug_str" => {
|
||||||
} else if reader.name() == ".debug_str_offsets" {
|
dwarf.debug_str = gimli::DebugStr::new(reader.data(), gimli::LittleEndian);
|
||||||
dwarf.debug_str_offsets = gimli::DebugStrOffsets::from(
|
}
|
||||||
gimli::EndianSlice::new(reader.data(), gimli::LittleEndian),
|
Payload::CustomSection(reader) if reader.name() == ".debug_str_offsets" => {
|
||||||
);
|
dwarf.debug_str_offsets = gimli::DebugStrOffsets::from(gimli::EndianSlice::new(
|
||||||
} else if reader.name() == ".debug_types" {
|
reader.data(),
|
||||||
dwarf.debug_types = gimli::DebugTypes::new(reader.data(), gimli::LittleEndian);
|
gimli::LittleEndian,
|
||||||
} else if reader.name() == ".debug_loc" {
|
));
|
||||||
extra_sections.debug_loc =
|
}
|
||||||
gimli::DebugLoc::new(reader.data(), gimli::LittleEndian);
|
Payload::CustomSection(reader) if reader.name() == ".debug_types" => {
|
||||||
} else if reader.name() == ".debug_loclists" {
|
dwarf.debug_types = gimli::DebugTypes::new(reader.data(), gimli::LittleEndian);
|
||||||
extra_sections.debug_loclists =
|
}
|
||||||
gimli::DebugLocLists::new(reader.data(), gimli::LittleEndian);
|
Payload::CustomSection(reader) if reader.name() == ".debug_loc" => {
|
||||||
} else if reader.name() == ".debug_ranges" {
|
extra_sections.debug_loc = gimli::DebugLoc::new(reader.data(), gimli::LittleEndian);
|
||||||
extra_sections.debug_ranges =
|
}
|
||||||
gimli::DebugRanges::new(reader.data(), gimli::LittleEndian);
|
Payload::CustomSection(reader) if reader.name() == ".debug_loclists" => {
|
||||||
} else if reader.name() == ".debug_rnglists" {
|
extra_sections.debug_loclists =
|
||||||
extra_sections.debug_rnglists =
|
gimli::DebugLocLists::new(reader.data(), gimli::LittleEndian);
|
||||||
gimli::DebugRngLists::new(reader.data(), gimli::LittleEndian);
|
}
|
||||||
}else{
|
Payload::CustomSection(reader) if reader.name() == ".debug_ranges" => {
|
||||||
module
|
extra_sections.debug_ranges =
|
||||||
.custom_sections
|
gimli::DebugRanges::new(reader.data(), gimli::LittleEndian);
|
||||||
.insert(reader.name().to_owned(), reader.data().to_owned());
|
}
|
||||||
}
|
Payload::CustomSection(reader) if reader.name() == ".debug_rnglists" => {
|
||||||
}
|
extra_sections.debug_rnglists =
|
||||||
_ => {}
|
gimli::DebugRngLists::new(reader.data(), gimli::LittleEndian);
|
||||||
},
|
}
|
||||||
|
Payload::CustomSection(reader) => {
|
||||||
|
module
|
||||||
|
.custom_sections
|
||||||
|
.insert(reader.name().to_owned(), reader.data().to_owned());
|
||||||
|
}
|
||||||
Payload::Version { .. } => {}
|
Payload::Version { .. } => {}
|
||||||
Payload::ElementSection(reader) => {
|
Payload::ElementSection(reader) => {
|
||||||
for element in reader {
|
for element in reader {
|
||||||
|
|
110
src/interp.rs
110
src/interp.rs
|
@ -6,7 +6,6 @@ use crate::ops::Operator;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
mod wasi;
|
mod wasi;
|
||||||
|
|
||||||
|
@ -19,7 +18,8 @@ pub struct InterpContext {
|
||||||
pub globals: PerEntity<Global, ConstVal>,
|
pub globals: PerEntity<Global, ConstVal>,
|
||||||
pub fuel: u64,
|
pub fuel: u64,
|
||||||
pub trace_handler: Option<Box<dyn Fn(usize, Vec<ConstVal>) -> bool + Send>>,
|
pub trace_handler: Option<Box<dyn Fn(usize, Vec<ConstVal>) -> bool + Send>>,
|
||||||
pub import_hander: Arc<dyn Fn(&mut InterpContext,&mut Module<'_>, &str, &[ConstVal]) -> InterpResult>,
|
pub import_hander:
|
||||||
|
Option<Box<dyn FnMut(&mut InterpContext, &str, &[ConstVal]) -> InterpResult>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type MultiVal = SmallVec<[ConstVal; 2]>;
|
type MultiVal = SmallVec<[ConstVal; 2]>;
|
||||||
|
@ -88,11 +88,11 @@ impl InterpContext {
|
||||||
globals,
|
globals,
|
||||||
fuel: u64::MAX,
|
fuel: u64::MAX,
|
||||||
trace_handler: None,
|
trace_handler: None,
|
||||||
import_hander: Arc::new(|_, _, _,_| InterpResult::TraceHandlerQuit),
|
import_hander: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call(&mut self, module: &mut Module<'_>, mut func: Func, args: &[ConstVal]) -> InterpResult {
|
pub fn call(&mut self, module: &Module<'_>, mut func: Func, args: &[ConstVal]) -> InterpResult {
|
||||||
let mut args = args.to_vec();
|
let mut args = args.to_vec();
|
||||||
'redo: loop {
|
'redo: loop {
|
||||||
let body = match &module.funcs[func] {
|
let body = match &module.funcs[func] {
|
||||||
|
@ -101,9 +101,9 @@ impl InterpContext {
|
||||||
FuncDecl::Import(..) => {
|
FuncDecl::Import(..) => {
|
||||||
let import = &module.imports[func.index()];
|
let import = &module.imports[func.index()];
|
||||||
assert_eq!(import.kind, ImportKind::Func(func));
|
assert_eq!(import.kind, ImportKind::Func(func));
|
||||||
return self.call_import(module,&import.name[..].to_owned(), &args);
|
return self.call_import(&import.name[..], &args);
|
||||||
}
|
}
|
||||||
FuncDecl::Body(_, _, body) => body.clone(),
|
FuncDecl::Body(_, _, body) => body,
|
||||||
FuncDecl::None => panic!("FuncDecl::None in call()"),
|
FuncDecl::None => panic!("FuncDecl::None in call()"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -178,25 +178,6 @@ impl InterpContext {
|
||||||
_ => return result,
|
_ => return result,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&ValueDef::Operator(Operator::CallRef { .. }, args, _) => {
|
|
||||||
let args = body.arg_pool[args]
|
|
||||||
.iter()
|
|
||||||
.map(|&arg| {
|
|
||||||
let arg = body.resolve_alias(arg);
|
|
||||||
let multivalue = frame.values.get(&arg).unwrap();
|
|
||||||
assert_eq!(multivalue.len(), 1);
|
|
||||||
multivalue[0]
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let ConstVal::Ref(Some(func)) = args.last().unwrap() else {
|
|
||||||
return InterpResult::TraceHandlerQuit;
|
|
||||||
};
|
|
||||||
let result = self.call(module, *func, &args[..args.len() - 1]);
|
|
||||||
match result {
|
|
||||||
InterpResult::Ok(vals) => vals,
|
|
||||||
_ => return result,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&ValueDef::Operator(ref op, args, _) => {
|
&ValueDef::Operator(ref op, args, _) => {
|
||||||
let args = body.arg_pool[args]
|
let args = body.arg_pool[args]
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -303,7 +284,7 @@ impl InterpContext {
|
||||||
return InterpResult::Trap(frame.func, frame.cur_block, u32::MAX)
|
return InterpResult::Trap(frame.func, frame.cur_block, u32::MAX)
|
||||||
}
|
}
|
||||||
&Terminator::Br { ref target } => {
|
&Terminator::Br { ref target } => {
|
||||||
frame.apply_target(&body, target);
|
frame.apply_target(body, target);
|
||||||
}
|
}
|
||||||
&Terminator::CondBr {
|
&Terminator::CondBr {
|
||||||
cond,
|
cond,
|
||||||
|
@ -314,9 +295,9 @@ impl InterpContext {
|
||||||
let cond = frame.values.get(&cond).unwrap();
|
let cond = frame.values.get(&cond).unwrap();
|
||||||
let cond = cond[0].as_u32().unwrap() != 0;
|
let cond = cond[0].as_u32().unwrap() != 0;
|
||||||
if cond {
|
if cond {
|
||||||
frame.apply_target(&body, if_true);
|
frame.apply_target(body, if_true);
|
||||||
} else {
|
} else {
|
||||||
frame.apply_target(&body, if_false);
|
frame.apply_target(body, if_false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Terminator::Select {
|
&Terminator::Select {
|
||||||
|
@ -328,9 +309,9 @@ impl InterpContext {
|
||||||
let value = frame.values.get(&value).unwrap();
|
let value = frame.values.get(&value).unwrap();
|
||||||
let value = value[0].as_u32().unwrap() as usize;
|
let value = value[0].as_u32().unwrap() as usize;
|
||||||
if value < targets.len() {
|
if value < targets.len() {
|
||||||
frame.apply_target(&body, &targets[value]);
|
frame.apply_target(body, &targets[value]);
|
||||||
} else {
|
} else {
|
||||||
frame.apply_target(&body, default);
|
frame.apply_target(body, default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Terminator::Return { ref values } => {
|
&Terminator::Return { ref values } => {
|
||||||
|
@ -344,35 +325,16 @@ impl InterpContext {
|
||||||
log::trace!("returning from {}: {:?}", func, values);
|
log::trace!("returning from {}: {:?}", func, values);
|
||||||
return InterpResult::Ok(values);
|
return InterpResult::Ok(values);
|
||||||
}
|
}
|
||||||
Terminator::ReturnCallRef {
|
Terminator::ReturnCallRef { sig, args } => todo!(),
|
||||||
sig,
|
|
||||||
args: ref args2,
|
|
||||||
} => {
|
|
||||||
let args2 = args2
|
|
||||||
.iter()
|
|
||||||
.map(|&arg| {
|
|
||||||
let arg = body.resolve_alias(arg);
|
|
||||||
let multivalue = frame.values.get(&arg).unwrap();
|
|
||||||
assert_eq!(multivalue.len(), 1);
|
|
||||||
multivalue[0]
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let ConstVal::Ref(Some(fu)) = args.last().unwrap() else {
|
|
||||||
return InterpResult::TraceHandlerQuit;
|
|
||||||
};
|
|
||||||
func = *fu;
|
|
||||||
args = args2[..args2.len() - 1].to_vec();
|
|
||||||
continue 'redo;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_import(&mut self,module: &mut Module<'_>, name: &str, args: &[ConstVal]) -> InterpResult {
|
fn call_import(&mut self, name: &str, args: &[ConstVal]) -> InterpResult {
|
||||||
let mut r = self.import_hander.clone();
|
let mut r = self.import_hander.take().unwrap();
|
||||||
let rs = r(self, module,name, args);
|
let rs = r(self, name, args);
|
||||||
// self.import_hander = Some(r);
|
self.import_hander = Some(r);
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -426,7 +388,6 @@ pub enum ConstVal {
|
||||||
I64(u64),
|
I64(u64),
|
||||||
F32(u32),
|
F32(u32),
|
||||||
F64(u64),
|
F64(u64),
|
||||||
Ref(Option<Func>),
|
|
||||||
#[default]
|
#[default]
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
@ -1034,32 +995,9 @@ pub fn const_eval(
|
||||||
ConstVal::None
|
ConstVal::None
|
||||||
}),
|
}),
|
||||||
|
|
||||||
(Operator::TableGet { table_index }, [ConstVal::I32(i)]) => ctx.and_then(|global| {
|
(Operator::TableGet { .. }, _)
|
||||||
Some(ConstVal::Ref(
|
| (Operator::TableSet { .. }, _)
|
||||||
global.tables[*table_index]
|
| (Operator::TableGrow { .. }, _) => None,
|
||||||
.elements
|
|
||||||
.get(*i as usize)
|
|
||||||
.and_then(|x| {
|
|
||||||
if *x == Func::invalid() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(*x)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
))
|
|
||||||
}),
|
|
||||||
(Operator::TableSet { table_index }, [ConstVal::I32(i), ConstVal::Ref(r)]) => {
|
|
||||||
ctx.and_then(|global| {
|
|
||||||
global.tables[*table_index].elements[*i as usize] = r.unwrap_or_default();
|
|
||||||
Some(ConstVal::I32(0))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
(Operator::TableGrow { table_index }, [ConstVal::I32(i)]) => ctx.and_then(|global| {
|
|
||||||
global.tables[*table_index]
|
|
||||||
.elements
|
|
||||||
.extend((0..*i).map(|a| Func::default()));
|
|
||||||
Some(ConstVal::I32(0))
|
|
||||||
}),
|
|
||||||
|
|
||||||
(Operator::TableSize { table_index }, []) => {
|
(Operator::TableSize { table_index }, []) => {
|
||||||
ctx.map(|global| ConstVal::I32(global.tables[*table_index].elements.len() as u32))
|
ctx.map(|global| ConstVal::I32(global.tables[*table_index].elements.len() as u32))
|
||||||
|
@ -1294,16 +1232,6 @@ pub fn const_eval(
|
||||||
write_u64(&mut global.memories[memory.memory], addr, *data);
|
write_u64(&mut global.memories[memory.memory], addr, *data);
|
||||||
Some(ConstVal::None)
|
Some(ConstVal::None)
|
||||||
}),
|
}),
|
||||||
(Operator::RefFunc { func_index }, []) => Some(ConstVal::Ref(Some(*func_index))),
|
|
||||||
(
|
|
||||||
Operator::RefNull {
|
|
||||||
ty: Type::FuncRef | Type::TypedFuncRef { .. },
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
) => Some(ConstVal::Ref(None)),
|
|
||||||
(Operator::RefIsNull, [ConstVal::Ref(r)]) => {
|
|
||||||
Some(ConstVal::I32(if r.is_none() { 1 } else { 0 }))
|
|
||||||
}
|
|
||||||
(_, args) if args.iter().any(|&arg| arg == ConstVal::None) => None,
|
(_, args) if args.iter().any(|&arg| arg == ConstVal::None) => None,
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use crate::{declare_entity, entity::EntityRef};
|
use crate::{declare_entity, entity::EntityRef};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
I32,
|
I32,
|
||||||
I64,
|
I64,
|
||||||
|
|
|
@ -9,7 +9,7 @@ use std::collections::HashMap;
|
||||||
declare_entity!(SourceFile, "file");
|
declare_entity!(SourceFile, "file");
|
||||||
declare_entity!(SourceLoc, "loc");
|
declare_entity!(SourceLoc, "loc");
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct Debug {
|
pub struct Debug {
|
||||||
pub source_files: EntityVec<SourceFile, String>,
|
pub source_files: EntityVec<SourceFile, String>,
|
||||||
source_file_dedup: HashMap<String, SourceFile>,
|
source_file_dedup: HashMap<String, SourceFile>,
|
||||||
|
@ -17,7 +17,7 @@ pub struct Debug {
|
||||||
source_loc_dedup: HashMap<SourceLocData, SourceLoc>,
|
source_loc_dedup: HashMap<SourceLocData, SourceLoc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct SourceLocData {
|
pub struct SourceLocData {
|
||||||
pub file: SourceFile,
|
pub file: SourceFile,
|
||||||
pub line: u32,
|
pub line: u32,
|
||||||
|
@ -46,7 +46,7 @@ impl Debug {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct DebugMap {
|
pub struct DebugMap {
|
||||||
/// Offset of code section relative to the Wasm file start.
|
/// Offset of code section relative to the Wasm file start.
|
||||||
pub code_offset: u32,
|
pub code_offset: u32,
|
||||||
|
|
|
@ -13,16 +13,16 @@ use std::collections::HashSet;
|
||||||
|
|
||||||
/// A declaration of a function: there is one `FuncDecl` per `Func`
|
/// A declaration of a function: there is one `FuncDecl` per `Func`
|
||||||
/// index.
|
/// index.
|
||||||
#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub enum FuncDecl<'a> {
|
pub enum FuncDecl<'a> {
|
||||||
/// An imported function.
|
/// An imported function.
|
||||||
Import(Signature, String),
|
Import(Signature, String),
|
||||||
/// An un-expanded body that can be lazily expanded if needed.
|
/// An un-expanded body that can be lazily expanded if needed.
|
||||||
#[serde(skip)]Lazy(Signature, String, wasmparser::FunctionBody<'a>),
|
Lazy(Signature, String, wasmparser::FunctionBody<'a>),
|
||||||
/// A modified or new function body that requires compilation.
|
/// A modified or new function body that requires compilation.
|
||||||
Body(Signature, String, FunctionBody),
|
Body(Signature, String, FunctionBody),
|
||||||
/// A compiled function body (was IR, has been collapsed back to bytecode).
|
/// A compiled function body (was IR, has been collapsed back to bytecode).
|
||||||
Compiled(Signature, String, Vec<u8>),
|
Compiled(Signature, String, wasm_encoder::Function),
|
||||||
/// A placeholder.
|
/// A placeholder.
|
||||||
#[default]
|
#[default]
|
||||||
None,
|
None,
|
||||||
|
@ -113,7 +113,7 @@ impl<'a> FuncDecl<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct FunctionBody {
|
pub struct FunctionBody {
|
||||||
/// How many parameters the function has. (Their types are the
|
/// How many parameters the function has. (Their types are the
|
||||||
/// first `n_params` values in `locals`.)
|
/// first `n_params` values in `locals`.)
|
||||||
|
@ -481,7 +481,7 @@ impl FunctionBody {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct BlockDef {
|
pub struct BlockDef {
|
||||||
/// Instructions in this block.
|
/// Instructions in this block.
|
||||||
pub insts: Vec<Value>,
|
pub insts: Vec<Value>,
|
||||||
|
@ -501,7 +501,7 @@ pub struct BlockDef {
|
||||||
pub desc: String,
|
pub desc: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct BlockTarget {
|
pub struct BlockTarget {
|
||||||
pub block: Block,
|
pub block: Block,
|
||||||
pub args: Vec<Value>,
|
pub args: Vec<Value>,
|
||||||
|
@ -518,7 +518,7 @@ impl std::fmt::Display for BlockTarget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum Terminator {
|
pub enum Terminator {
|
||||||
Br {
|
Br {
|
||||||
target: BlockTarget,
|
target: BlockTarget,
|
||||||
|
|
|
@ -7,7 +7,7 @@ use indexmap::IndexMap;
|
||||||
|
|
||||||
pub use crate::frontend::FrontendOptions;
|
pub use crate::frontend::FrontendOptions;
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Module<'a> {
|
pub struct Module<'a> {
|
||||||
pub orig_bytes: &'a [u8],
|
pub orig_bytes: &'a [u8],
|
||||||
pub funcs: EntityVec<Func, FuncDecl<'a>>,
|
pub funcs: EntityVec<Func, FuncDecl<'a>>,
|
||||||
|
@ -23,13 +23,13 @@ pub struct Module<'a> {
|
||||||
pub custom_sections: IndexMap<String, Vec<u8>>,
|
pub custom_sections: IndexMap<String, Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct SignatureData {
|
pub struct SignatureData {
|
||||||
pub params: Vec<Type>,
|
pub params: Vec<Type>,
|
||||||
pub returns: Vec<Type>,
|
pub returns: Vec<Type>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct MemoryData {
|
pub struct MemoryData {
|
||||||
pub initial_pages: usize,
|
pub initial_pages: usize,
|
||||||
pub maximum_pages: Option<usize>,
|
pub maximum_pages: Option<usize>,
|
||||||
|
@ -38,22 +38,21 @@ pub struct MemoryData {
|
||||||
pub shared: bool,
|
pub shared: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct MemorySegment {
|
pub struct MemorySegment {
|
||||||
pub offset: usize,
|
pub offset: usize,
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct TableData {
|
pub struct TableData {
|
||||||
pub ty: Type,
|
pub ty: Type,
|
||||||
pub table64: bool,
|
pub initial: u32,
|
||||||
pub initial: u64,
|
pub max: Option<u32>,
|
||||||
pub max: Option<u64>,
|
|
||||||
pub func_elements: Option<Vec<Func>>,
|
pub func_elements: Option<Vec<Func>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct GlobalData {
|
pub struct GlobalData {
|
||||||
pub ty: Type,
|
pub ty: Type,
|
||||||
pub value: Option<u64>,
|
pub value: Option<u64>,
|
||||||
|
@ -82,14 +81,14 @@ impl From<wasmparser::FuncType> for SignatureData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Import {
|
pub struct Import {
|
||||||
pub module: String,
|
pub module: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub kind: ImportKind,
|
pub kind: ImportKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum ImportKind {
|
pub enum ImportKind {
|
||||||
Table(Table),
|
Table(Table),
|
||||||
Func(Func),
|
Func(Func),
|
||||||
|
@ -109,13 +108,13 @@ impl std::fmt::Display for ImportKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Export {
|
pub struct Export {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub kind: ExportKind,
|
pub kind: ExportKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum ExportKind {
|
pub enum ExportKind {
|
||||||
Table(Table),
|
Table(Table),
|
||||||
Func(Func),
|
Func(Func),
|
||||||
|
@ -178,14 +177,13 @@ impl<'a> Module<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Module<'a> {
|
impl<'a> Module<'a> {
|
||||||
pub(crate) fn frontend_add_table(&mut self, ty: Type, initial: u64, max: Option<u64>, table64: bool) -> Table {
|
pub(crate) fn frontend_add_table(&mut self, ty: Type, initial: u32, max: Option<u32>) -> Table {
|
||||||
let func_elements = Some(vec![]);
|
let func_elements = Some(vec![]);
|
||||||
self.tables.push(TableData {
|
self.tables.push(TableData {
|
||||||
ty,
|
ty,
|
||||||
func_elements,
|
func_elements,
|
||||||
initial,
|
initial,
|
||||||
max,
|
max,
|
||||||
table64
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use super::{Block, Type, Value};
|
||||||
use crate::pool::{ListPool, ListRef};
|
use crate::pool::{ListPool, ListRef};
|
||||||
use crate::Operator;
|
use crate::Operator;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||||
pub enum ValueDef {
|
pub enum ValueDef {
|
||||||
BlockParam(Block, u32, Type),
|
BlockParam(Block, u32, Type),
|
||||||
Operator(Operator, ListRef<Value>, ListRef<Type>),
|
Operator(Operator, ListRef<Value>, ListRef<Type>),
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
// Re-export wasmparser for easier use of the right version by our embedders.
|
// Re-export wasmparser for easier use of the right version by our embedders.
|
||||||
pub use wasmparser;
|
pub use wasmparser;
|
||||||
// Likewise for wasm-encoder.
|
|
||||||
pub use wasm_encoder;
|
|
||||||
|
|
||||||
mod backend;
|
mod backend;
|
||||||
pub mod cfg;
|
pub mod cfg;
|
||||||
|
|
|
@ -257,24 +257,12 @@ pub fn op_inputs(
|
||||||
Operator::F64ReinterpretI64 => Ok(Cow::Borrowed(&[Type::I64])),
|
Operator::F64ReinterpretI64 => Ok(Cow::Borrowed(&[Type::I64])),
|
||||||
Operator::I32ReinterpretF32 => Ok(Cow::Borrowed(&[Type::F32])),
|
Operator::I32ReinterpretF32 => Ok(Cow::Borrowed(&[Type::F32])),
|
||||||
Operator::I64ReinterpretF64 => Ok(Cow::Borrowed(&[Type::F64])),
|
Operator::I64ReinterpretF64 => Ok(Cow::Borrowed(&[Type::F64])),
|
||||||
Operator::TableGet { table_index } => if module.tables[*table_index].table64{
|
Operator::TableGet { .. } => Ok(Cow::Borrowed(&[Type::I32])),
|
||||||
Ok(Cow::Borrowed(&[Type::I64]))
|
|
||||||
}else{
|
|
||||||
Ok(Cow::Borrowed(&[Type::I32]))
|
|
||||||
},
|
|
||||||
Operator::TableSet { table_index } => {
|
Operator::TableSet { table_index } => {
|
||||||
Ok(vec![if module.tables[*table_index].table64{
|
Ok(vec![Type::I32, module.tables[*table_index].ty].into())
|
||||||
Type::I64
|
|
||||||
}else{
|
|
||||||
Type::I32
|
|
||||||
}, module.tables[*table_index].ty].into())
|
|
||||||
}
|
}
|
||||||
Operator::TableGrow { table_index } => {
|
Operator::TableGrow { table_index } => {
|
||||||
Ok(vec![if module.tables[*table_index].table64{
|
Ok(vec![Type::I32, module.tables[*table_index].ty].into())
|
||||||
Type::I64
|
|
||||||
}else{
|
|
||||||
Type::I32
|
|
||||||
}, module.tables[*table_index].ty].into())
|
|
||||||
}
|
}
|
||||||
Operator::TableSize { .. } => Ok(Cow::Borrowed(&[])),
|
Operator::TableSize { .. } => Ok(Cow::Borrowed(&[])),
|
||||||
Operator::MemorySize { .. } => Ok(Cow::Borrowed(&[])),
|
Operator::MemorySize { .. } => Ok(Cow::Borrowed(&[])),
|
||||||
|
@ -1314,11 +1302,7 @@ pub fn op_outputs(
|
||||||
Operator::TableGet { table_index } => Ok(vec![module.tables[*table_index].ty].into()),
|
Operator::TableGet { table_index } => Ok(vec![module.tables[*table_index].ty].into()),
|
||||||
Operator::TableSet { .. } => Ok(Cow::Borrowed(&[])),
|
Operator::TableSet { .. } => Ok(Cow::Borrowed(&[])),
|
||||||
Operator::TableGrow { .. } => Ok(Cow::Borrowed(&[])),
|
Operator::TableGrow { .. } => Ok(Cow::Borrowed(&[])),
|
||||||
Operator::TableSize { table_index } => Ok(Cow::Borrowed(if module.tables[*table_index].table64{
|
Operator::TableSize { .. } => Ok(Cow::Borrowed(&[Type::I32])),
|
||||||
&[Type::I64]
|
|
||||||
}else{
|
|
||||||
&[Type::I32]
|
|
||||||
})),
|
|
||||||
Operator::MemorySize { mem } => Ok(if module.memories[*mem].memory64 {
|
Operator::MemorySize { mem } => Ok(if module.memories[*mem].memory64 {
|
||||||
Cow::Borrowed(&[Type::I64])
|
Cow::Borrowed(&[Type::I64])
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -5,7 +5,7 @@ use anyhow::Context;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
pub use wasmparser::{Ieee32, Ieee64};
|
pub use wasmparser::{Ieee32, Ieee64};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct MemoryArg {
|
pub struct MemoryArg {
|
||||||
pub align: u32,
|
pub align: u32,
|
||||||
pub offset: u64 ,
|
pub offset: u64 ,
|
||||||
|
@ -23,7 +23,7 @@ impl std::fmt::Display for MemoryArg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum Operator {
|
pub enum Operator {
|
||||||
Unreachable,
|
Unreachable,
|
||||||
Nop,
|
Nop,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{collections::BTreeMap, convert::Infallible, iter::{empty, once}};
|
use std::{collections::BTreeMap, convert::Infallible, iter::empty};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
// use libc::name_t;
|
// use libc::name_t;
|
||||||
|
@ -55,7 +55,7 @@ impl Fuse {
|
||||||
target: d,
|
target: d,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
pub fn finalize(self, m: &mut Module) -> Memory {
|
pub fn finalize(self, m: &mut Module) -> Memory{
|
||||||
let mem = m.memories[self.target].clone();
|
let mem = m.memories[self.target].clone();
|
||||||
m.memories = EntityVec::default();
|
m.memories = EntityVec::default();
|
||||||
let new = m.memories.push(mem);
|
let new = m.memories.push(mem);
|
||||||
|
@ -110,7 +110,7 @@ impl Fuse {
|
||||||
// }
|
// }
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
pub fn process(&self, m: &mut Module, f: &mut FunctionBody) {
|
pub fn process(&self, f: &mut FunctionBody) {
|
||||||
let vz = f.arg_pool.from_iter(empty());
|
let vz = f.arg_pool.from_iter(empty());
|
||||||
let tz = f.type_pool.from_iter(empty());
|
let tz = f.type_pool.from_iter(empty());
|
||||||
let ti = f.type_pool.from_iter(vec![Type::I32].into_iter());
|
let ti = f.type_pool.from_iter(vec![Type::I32].into_iter());
|
||||||
|
@ -123,42 +123,6 @@ impl Fuse {
|
||||||
// let vi = v;
|
// let vi = v;
|
||||||
if let ValueDef::Operator(a, b, c) = &mut w {
|
if let ValueDef::Operator(a, b, c) = &mut w {
|
||||||
let mut bp = f.arg_pool[*b].to_vec();
|
let mut bp = f.arg_pool[*b].to_vec();
|
||||||
fn g(
|
|
||||||
a: impl for<'a> FnMut(&mut Module,&mut FunctionBody, Memory, &'a mut crate::Value),
|
|
||||||
) -> impl for<'a> FnMut(&mut Module,&mut FunctionBody, Memory, &'a mut crate::Value)
|
|
||||||
{
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
let mut p = g(|m: &mut Module,f, mem, v| {
|
|
||||||
match (m.memories[mem].memory64, m.memories[self.target].memory64) {
|
|
||||||
(true, true) => {}
|
|
||||||
(true, false) => {
|
|
||||||
let ti = f.type_pool.from_iter(once(Type::I32));
|
|
||||||
let w = f.arg_pool.from_iter(vec![*v].into_iter());
|
|
||||||
let x = f.add_value(ValueDef::Operator(
|
|
||||||
Operator::I32WrapI64,
|
|
||||||
w,
|
|
||||||
ti,
|
|
||||||
));
|
|
||||||
f.append_to_block(k, x);
|
|
||||||
// crate::append_before(f, x, vi, k);
|
|
||||||
*v = x;
|
|
||||||
}
|
|
||||||
(false, true) => {
|
|
||||||
let ti = f.type_pool.from_iter(once(Type::I64));
|
|
||||||
let w = f.arg_pool.from_iter(vec![*v].into_iter());
|
|
||||||
let x = f.add_value(ValueDef::Operator(
|
|
||||||
Operator::I64ExtendI32U,
|
|
||||||
w,
|
|
||||||
ti,
|
|
||||||
));
|
|
||||||
f.append_to_block(k, x);
|
|
||||||
// crate::append_before(f, x, vi, k);
|
|
||||||
*v = x;
|
|
||||||
},
|
|
||||||
(false, false) => {}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
match a.clone() {
|
match a.clone() {
|
||||||
Operator::MemorySize { mem } => {
|
Operator::MemorySize { mem } => {
|
||||||
if mem != self.target {
|
if mem != self.target {
|
||||||
|
@ -175,7 +139,6 @@ impl Fuse {
|
||||||
function_index: self.size,
|
function_index: self.size,
|
||||||
};
|
};
|
||||||
bp.push(ia);
|
bp.push(ia);
|
||||||
p(m,f, mem, &mut bp[0]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Operator::MemoryGrow { mem } => {
|
Operator::MemoryGrow { mem } => {
|
||||||
|
@ -193,22 +156,20 @@ impl Fuse {
|
||||||
function_index: self.grow,
|
function_index: self.grow,
|
||||||
};
|
};
|
||||||
bp.push(ia);
|
bp.push(ia);
|
||||||
p(m, f,mem, &mut bp[0]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => crate::op_traits::rewrite_mem(a, &mut bp, |mem, v| {
|
_ => crate::op_traits::rewrite_mem(a, &mut bp, |m, v| {
|
||||||
if *mem != self.target {
|
if *m != self.target{
|
||||||
let ia = f.add_value(ValueDef::Operator(
|
let ia = f.add_value(ValueDef::Operator(
|
||||||
Operator::I32Const {
|
Operator::I32Const {
|
||||||
value: mem.index() as u32,
|
value: m.index() as u32,
|
||||||
},
|
},
|
||||||
vz,
|
vz,
|
||||||
ti,
|
ti,
|
||||||
));
|
));
|
||||||
f.append_to_block(k, ia);
|
f.append_to_block(k, ia);
|
||||||
// append_before(f, ia, vi, k);
|
// append_before(f, ia, vi, k);
|
||||||
if let Some(v) = v {
|
if let Some(v) = v {
|
||||||
p(m,f, *mem, &mut *v);
|
|
||||||
let w = f.arg_pool.from_iter(vec![*v, ia].into_iter());
|
let w = f.arg_pool.from_iter(vec![*v, ia].into_iter());
|
||||||
let x = f.add_value(ValueDef::Operator(
|
let x = f.add_value(ValueDef::Operator(
|
||||||
Operator::Call {
|
Operator::Call {
|
||||||
|
@ -221,11 +182,10 @@ impl Fuse {
|
||||||
// crate::append_before(f, x, vi, k);
|
// crate::append_before(f, x, vi, k);
|
||||||
*v = x;
|
*v = x;
|
||||||
}
|
}
|
||||||
*mem = self.target;
|
*m = self.target;
|
||||||
}
|
}
|
||||||
Ok::<(), Infallible>(())
|
Ok::<(),Infallible>(())
|
||||||
})
|
}).unwrap(),
|
||||||
.unwrap(),
|
|
||||||
}
|
}
|
||||||
*b = *ka
|
*b = *ka
|
||||||
.entry(bp.clone())
|
.entry(bp.clone())
|
||||||
|
@ -241,7 +201,7 @@ pub fn fuse(m: &mut Module) -> anyhow::Result<()> {
|
||||||
let f = Fuse::new(m).context("in getting the fuse funcs")?;
|
let f = Fuse::new(m).context("in getting the fuse funcs")?;
|
||||||
crate::passes::unmem::metafuse_all(m, &mut crate::passes::unmem::All {});
|
crate::passes::unmem::metafuse_all(m, &mut crate::passes::unmem::All {});
|
||||||
// crate::passes::splice::splice_module(m)?;
|
// crate::passes::splice::splice_module(m)?;
|
||||||
m.take_per_func_body(|m, b| f.process(m, b));
|
m.per_func_body(|b| f.process(b));
|
||||||
f.finalize(m);
|
f.finalize(m);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::fmt::Debug;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ListPool<T: Clone + Debug> {
|
pub struct ListPool<T: Clone + Debug> {
|
||||||
pub storage: Vec<T>,
|
pub storage: Vec<T>,
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ impl<T: Clone + Debug> Default for ListPool<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct ListRef<T>(u32, u32, PhantomData<T>);
|
pub struct ListRef<T>(u32, u32, PhantomData<T>);
|
||||||
|
|
||||||
impl<T> Default for ListRef<T> {
|
impl<T> Default for ListRef<T> {
|
||||||
|
|
Loading…
Reference in a new issue