Skip to content

Commit b254c7e

Browse files
authored
Use [u8] instead of [u16] to not rely on alignment (#736)
#46 --------- Co-authored-by: Zhou Fang <[email protected]>
1 parent 2b0ae56 commit b254c7e

File tree

9 files changed

+56
-78
lines changed

9 files changed

+56
-78
lines changed

crates/interpreter/Cargo.lock

Lines changed: 0 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/interpreter/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ keywords = ["embedded", "framework", "no-std", "wasm"]
1212
categories = ["embedded", "no-std", "wasm"]
1313

1414
[dependencies]
15-
bytemuck = { version = "1.16.0", default-features = false, features = ["derive"] }
1615
libm = { version = "0.2.8", default-features = false, optional = true }
1716
num_enum = { version = "0.7.2", default-features = false }
1817
paste = { version = "1.0.15", default-features = false }

crates/interpreter/src/module.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ use crate::*;
2828
pub struct Module<'m> {
2929
binary: &'m [u8],
3030
types: Vec<FuncType<'m>>,
31-
// TODO(dev/fast-interp): Use a shallow (unstructured) view in the flash.
31+
// TODO(dev/fast-interp): Change the type to `SideTableView` which will be parsed by
32+
// `new_unchecked()`.
3233
side_table: &'m [MetadataEntry],
3334
}
3435

crates/interpreter/src/side_table.rs

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,43 +20,37 @@ use crate::module::Parser;
2020

2121
pub struct SideTableView<'m> {
2222
pub func_idx: usize,
23-
pub indices: &'m [u16], // including 0 and the length of metadata_array
24-
pub metadata: &'m [u16],
23+
pub indices: &'m [u8], // including 0 and the length of metadata_array
24+
pub metadata: &'m [u8],
2525
}
2626

2727
impl<'m> SideTableView<'m> {
28-
pub fn new(parser: &mut crate::valid::Parser<'m>) -> Result<Self, Error> {
28+
pub fn new(binary: &'m [u8]) -> Result<Self, Error> {
29+
let num_functions = parse_u16(binary, 0) as usize;
30+
let indices_end = 2 + (num_functions + 1) * 2;
2931
Ok(SideTableView {
3032
func_idx: 0,
31-
indices: parse_side_table_field(parser)?,
32-
metadata: parse_side_table_field(parser)?,
33+
indices: &binary[2 .. indices_end],
34+
metadata: &binary[indices_end ..],
3335
})
3436
}
3537

38+
// TODO(dev/fast-interp): Make it generic since it will be used in both `Check` and `Use` modes.
39+
// (Returns `MResult<Metadata<'m>, M>` instead.)
3640
pub fn metadata(&self, func_idx: usize) -> Metadata<'m> {
3741
Metadata(
38-
&self.metadata[self.indices[func_idx] as usize .. self.indices[func_idx + 1] as usize],
42+
&self.metadata[parse_u16(self.indices, func_idx * 2) as usize
43+
.. parse_u16(self.indices, (func_idx + 1) * 2) as usize],
3944
)
4045
}
4146
}
4247

43-
fn parse_u16(data: &[u8]) -> u16 {
44-
bytemuck::pod_read_unaligned::<u16>(bytemuck::cast_slice(&data[0 .. 2]))
45-
}
46-
47-
fn parse_side_table_field<'m>(parser: &mut crate::valid::Parser<'m>) -> Result<&'m [u16], Error> {
48-
let len = parse_u16(parser.save()) as usize;
49-
let parser = parser.split_at(len)?;
50-
let bytes = parser.save().get(0 .. len * 2).unwrap();
51-
Ok(bytemuck::cast_slice::<_, u16>(bytes))
52-
}
53-
5448
#[derive(Default, Copy, Clone)]
55-
pub struct Metadata<'m>(&'m [u16]);
49+
pub struct Metadata<'m>(&'m [u8]);
5650

5751
impl<'m> Metadata<'m> {
5852
pub fn type_idx(&self) -> usize {
59-
self.0[0] as usize
53+
parse_u16(self.0, 0) as usize
6054
}
6155

6256
#[allow(dead_code)]
@@ -65,15 +59,23 @@ impl<'m> Metadata<'m> {
6559
}
6660

6761
pub fn branch_table(&self) -> &[BranchTableEntry] {
68-
bytemuck::cast_slice(&self.0[5 ..])
62+
let entry_size = size_of::<BranchTableEntry>();
63+
assert_eq!(
64+
(self.0.len() - 10) % entry_size,
65+
0,
66+
"Metadata length for branch table must be divisible by {} bytes",
67+
entry_size
68+
);
69+
unsafe {
70+
core::slice::from_raw_parts(
71+
self.0[10 ..].as_ptr() as *const BranchTableEntry,
72+
self.0.len() / entry_size,
73+
)
74+
}
6975
}
7076

7177
pub fn parser_range(&self) -> Range<usize> {
72-
self.read_u32(1) .. self.read_u32(3)
73-
}
74-
75-
fn read_u32(&self, idx: usize) -> usize {
76-
bytemuck::pod_read_unaligned::<u32>(bytemuck::cast_slice(&self.0[idx .. idx + 2])) as usize
78+
parse_u32(self.0, 2) as usize .. parse_u32(self.0, 6) as usize
7779
}
7880
}
7981

@@ -84,9 +86,9 @@ pub struct MetadataEntry {
8486
pub branch_table: Vec<BranchTableEntry>,
8587
}
8688

87-
#[derive(Copy, Clone, Debug, bytemuck::AnyBitPattern)]
89+
#[derive(Copy, Clone, Debug)]
8890
#[repr(transparent)]
89-
pub struct BranchTableEntry([u16; 3]);
91+
pub struct BranchTableEntry([u8; 6]);
9092

9193
pub struct BranchTableEntryView {
9294
/// The amount to adjust the instruction pointer by if the branch is taken.
@@ -105,27 +107,42 @@ impl BranchTableEntry {
105107
debug_assert!((i16::MIN as i32 .. i16::MAX as i32).contains(&view.delta_stp));
106108
debug_assert!(view.val_cnt <= 0xf);
107109
debug_assert!(view.pop_cnt <= 0xfff);
110+
let delta_ip_bytes = (view.delta_ip as u16).to_le_bytes();
111+
let delta_stp_bytes = (view.delta_stp as u16).to_le_bytes();
112+
let pop_val_counts_bytes = (((view.pop_cnt << 4) | view.val_cnt) as u16).to_le_bytes();
108113
Ok(BranchTableEntry([
109-
view.delta_ip as u16,
110-
view.delta_stp as u16,
111-
((view.pop_cnt << 4) | view.val_cnt) as u16,
114+
delta_ip_bytes[0],
115+
delta_ip_bytes[1],
116+
delta_stp_bytes[0],
117+
delta_stp_bytes[1],
118+
pop_val_counts_bytes[0],
119+
pop_val_counts_bytes[1],
112120
]))
113121
}
114122

115123
pub fn view(self) -> BranchTableEntryView {
124+
let pop_val_counts = parse_u16(&self.0, 4);
116125
BranchTableEntryView {
117-
delta_ip: (self.0[0] as i16) as i32,
118-
delta_stp: (self.0[1] as i16) as i32,
119-
val_cnt: (self.0[2] & 0xf) as u32,
120-
pop_cnt: (self.0[2] >> 4) as u32,
126+
delta_ip: (parse_u16(&self.0, 0) as i16) as i32,
127+
delta_stp: (parse_u16(&self.0, 2) as i16) as i32,
128+
val_cnt: (pop_val_counts & 0xf) as u32,
129+
pop_cnt: (pop_val_counts >> 4) as u32,
121130
}
122131
}
123132

124133
pub fn is_invalid(self) -> bool {
125-
self.0 == [0; 3]
134+
self.0 == [0; 6]
126135
}
127136

128137
pub fn invalid() -> Self {
129-
BranchTableEntry([0; 3])
138+
BranchTableEntry([0; 6])
130139
}
131140
}
141+
142+
fn parse_u16(data: &[u8], offset: usize) -> u16 {
143+
u16::from_le_bytes(data[offset ..][.. 2].try_into().unwrap())
144+
}
145+
146+
fn parse_u32(data: &[u8], offset: usize) -> u32 {
147+
u32::from_le_bytes(data[offset ..][.. 4].try_into().unwrap())
148+
}

crates/interpreter/src/valid.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ impl ValidMode for Verify {
146146
check(parser.parse_section_id()? == SectionId::Custom)?;
147147
let mut section = parser.split_section()?;
148148
check(section.parse_name()? == "wasefire-sidetable")?;
149-
SideTableView::new(parser)
149+
SideTableView::new(parser.save())
150150
}
151151

152152
fn next_branch_table<'a, 'm>(

crates/runner-host/Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/runner-nordic/Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/scheduler/Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/wasm-bench/Cargo.lock

Lines changed: 0 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)