diff --git a/crates/interpreter/Cargo.lock b/crates/interpreter/Cargo.lock index 13a3fe82..a9864d07 100644 --- a/crates/interpreter/Cargo.lock +++ b/crates/interpreter/Cargo.lock @@ -14,26 +14,6 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" -[[package]] -name = "bytemuck" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -170,7 +150,6 @@ dependencies = [ name = "wasefire-interpreter" version = "0.3.2-git" dependencies = [ - "bytemuck", "lazy_static", "libm", "num_enum", diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index 269ee68b..b842b4ee 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -12,7 +12,6 @@ keywords = ["embedded", "framework", "no-std", "wasm"] categories = ["embedded", "no-std", "wasm"] [dependencies] -bytemuck = { version = "1.16.0", default-features = false, features = ["derive"] } libm = { version = "0.2.8", default-features = false, optional = true } num_enum = { version = "0.7.2", default-features = false } paste = { version = "1.0.15", default-features = false } diff --git a/crates/interpreter/src/module.rs b/crates/interpreter/src/module.rs index 18a6b726..ee5bed46 100644 --- a/crates/interpreter/src/module.rs +++ b/crates/interpreter/src/module.rs @@ -28,7 +28,8 @@ use crate::*; pub struct Module<'m> { binary: &'m [u8], types: Vec>, - // TODO(dev/fast-interp): Use a shallow (unstructured) view in the flash. + // TODO(dev/fast-interp): Change the type to `SideTableView` which will be parsed by + // `new_unchecked()`. side_table: &'m [MetadataEntry], } diff --git a/crates/interpreter/src/side_table.rs b/crates/interpreter/src/side_table.rs index 06ecc5da..0f93a5a7 100644 --- a/crates/interpreter/src/side_table.rs +++ b/crates/interpreter/src/side_table.rs @@ -26,7 +26,7 @@ pub struct SideTableView<'m> { impl<'m> SideTableView<'m> { pub fn new(binary: &'m [u8]) -> Result { - let num_functions = u16::from_le_bytes(binary[.. 2].try_into().unwrap()) as usize; + let num_functions = parse_u16(binary, 0) as usize; let indices_end = 2 + (num_functions + 1) * 2; Ok(SideTableView { func_idx: 0, @@ -35,6 +35,8 @@ impl<'m> SideTableView<'m> { }) } + // TODO(dev/fast-interp): Make it generic since it will be used in both `Check` and `Use` modes. + // (Returns `MResult, M>` instead.) pub fn metadata(&self, func_idx: usize) -> Metadata<'m> { Metadata( &self.metadata[parse_u16(self.indices, func_idx * 2) as usize @@ -43,16 +45,12 @@ impl<'m> SideTableView<'m> { } } -fn parse_u16(data: &[u8], offset: usize) -> u16 { - u16::from_le_bytes(data[offset ..][.. 2].try_into().unwrap()) -} - #[derive(Default, Copy, Clone)] pub struct Metadata<'m>(&'m [u8]); impl<'m> Metadata<'m> { pub fn type_idx(&self) -> usize { - u16::from_le_bytes(self.0[.. 2].try_into().unwrap()) as usize + parse_u16(self.0, 0) as usize } #[allow(dead_code)] @@ -61,15 +59,23 @@ impl<'m> Metadata<'m> { } pub fn branch_table(&self) -> &[BranchTableEntry] { - bytemuck::cast_slice(&self.0[10 ..]) + let entry_size = 6; + assert_eq!( + self.0.len() % entry_size, + 0, + "Metadata length must be divisible by {} bytes", + entry_size + ); + unsafe { + core::slice::from_raw_parts( + self.0.as_ptr() as *const BranchTableEntry, + self.0.len() / entry_size, + ) + } } pub fn parser_range(&self) -> Range { - self.read_u32(2) .. self.read_u32(6) - } - - fn read_u32(&self, idx: usize) -> usize { - u32::from_le_bytes(self.0[idx .. idx + 4].try_into().unwrap()) as usize + parse_u32(self.0, 2) as usize .. parse_u32(self.0, 6) as usize } } @@ -80,9 +86,9 @@ pub struct MetadataEntry { pub branch_table: Vec, } -#[derive(Copy, Clone, Debug, bytemuck::AnyBitPattern)] +#[derive(Copy, Clone, Debug)] #[repr(transparent)] -pub struct BranchTableEntry([u16; 3]); +pub struct BranchTableEntry([u8; 6]); pub struct BranchTableEntryView { /// The amount to adjust the instruction pointer by if the branch is taken. @@ -101,27 +107,42 @@ impl BranchTableEntry { debug_assert!((i16::MIN as i32 .. i16::MAX as i32).contains(&view.delta_stp)); debug_assert!(view.val_cnt <= 0xf); debug_assert!(view.pop_cnt <= 0xfff); + let delta_ip_bytes = (view.delta_ip as u16).to_le_bytes(); + let delta_stp_bytes = (view.delta_stp as u16).to_le_bytes(); + let pop_val_counts_bytes = (((view.pop_cnt << 4) | view.val_cnt) as u16).to_le_bytes(); Ok(BranchTableEntry([ - view.delta_ip as u16, - view.delta_stp as u16, - ((view.pop_cnt << 4) | view.val_cnt) as u16, + delta_ip_bytes[0], + delta_ip_bytes[1], + delta_stp_bytes[0], + delta_stp_bytes[1], + pop_val_counts_bytes[0], + pop_val_counts_bytes[1], ])) } pub fn view(self) -> BranchTableEntryView { + let pop_val_counts = parse_u16(&self.0, 4); BranchTableEntryView { - delta_ip: (self.0[0] as i16) as i32, - delta_stp: (self.0[1] as i16) as i32, - val_cnt: (self.0[2] & 0xf) as u32, - pop_cnt: (self.0[2] >> 4) as u32, + delta_ip: (parse_u16(&self.0, 0) as i16) as i32, + delta_stp: (parse_u16(&self.0, 2) as i16) as i32, + val_cnt: (pop_val_counts & 0xf) as u32, + pop_cnt: (pop_val_counts >> 4) as u32, } } pub fn is_invalid(self) -> bool { - self.0 == [0; 3] + self.0 == [0; 6] } pub fn invalid() -> Self { - BranchTableEntry([0; 3]) + BranchTableEntry([0; 6]) } } + +fn parse_u16(data: &[u8], offset: usize) -> u16 { + u16::from_le_bytes(data[offset ..][.. 2].try_into().unwrap()) +} + +fn parse_u32(data: &[u8], offset: usize) -> u32 { + u32::from_le_bytes(data[offset ..][.. 4].try_into().unwrap()) +}