Skip to content

Commit cda46ed

Browse files
committed
refactor!: merge "Abstract lower-level components"
1 parent 2f1e05d commit cda46ed

File tree

1 file changed

+106
-108
lines changed

1 file changed

+106
-108
lines changed

crates/interpreter/src/valid.rs

Lines changed: 106 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -33,129 +33,93 @@ pub fn prepare(binary: &[u8]) -> Result<Vec<MetadataEntry>, Error> {
3333

3434
#[allow(dead_code)]
3535
#[allow(unused_variables)]
36-
// Checks whether a WASM module with the side table in binary format is valid.
36+
/// Checks whether a WASM module with the side table in binary format is valid.
3737
pub fn verify(binary: &[u8]) -> Result<(), Error> {
3838
todo!()
3939
}
4040

4141
trait ValidMode: Default {
42-
type LabelBranches<'m>: Default;
43-
44-
fn end_label(expr: &mut Expr<Self>) -> CheckResult;
45-
46-
fn br_label<'m>(expr: &mut Expr<'_, 'm, Self>, l: LabelIdx) -> Result<ResultType<'m>, Error>;
42+
/// List of source branches, when preparing.
43+
///
44+
/// When verifying, contains at most one _target_ branch. Source branches are eagerly patched to
45+
/// their target branch using the branch table.
46+
type Branches<'m>: Default + IntoIterator<Item = SideTableBranch<'m>>;
47+
48+
/// Branch table to prepare or verify.
49+
type BranchTable<'m>;
50+
51+
/// Updates the branch table for source according to target, when preparing.
52+
///
53+
/// When verifying, makes sure source is target branch.
54+
fn stitch_branch<'m>(
55+
expr: &mut Expr<'_, 'm, Self>, source: SideTableBranch<'m>, target: SideTableBranch<'m>,
56+
) -> CheckResult;
57+
58+
/// Pushes a source branch, when preparing.
59+
///
60+
/// When verifying, only push if there are no branches already. If there is one, verify that
61+
/// it's the same.
62+
fn push_branch<'m>(
63+
branches: &mut Self::Branches<'m>, branch: SideTableBranch<'m>,
64+
) -> CheckResult;
65+
66+
/// Does nothing, when preparing.
67+
///
68+
/// When verifying, patches a source branch to its target branch using the branch table.
69+
fn patch_branch<'m>(
70+
table: &Self::BranchTable<'m>, source: SideTableBranch<'m>,
71+
) -> Result<SideTableBranch<'m>, Error>;
4772
}
4873

4974
#[derive(Default)]
5075
struct Prepare;
5176
impl ValidMode for Prepare {
52-
type LabelBranches<'m> = Vec<SideTableBranch<'m>>;
77+
type Branches<'m> = Vec<SideTableBranch<'m>>;
78+
type BranchTable<'m> = BranchTable;
5379

54-
fn end_label(expr: &mut Expr<Self>) -> CheckResult {
55-
let results_len = expr.label().type_.results.len();
56-
let mut target = expr.branch_target(results_len);
57-
for source in core::mem::take(&mut expr.label().branches) {
58-
expr.branch_table.stitch(source, target)?;
59-
}
60-
let label = expr.label();
61-
if let LabelKind::If(source) = label.kind {
62-
check(label.type_.params == label.type_.results)?;
63-
// SAFETY: This function is only called after parsing an End instruction.
64-
target.parser = offset_front(target.parser, -1);
65-
expr.branch_table.stitch(source, target)?;
66-
}
67-
let results = expr.label().type_.results;
68-
expr.pops(results)?;
69-
check(expr.labels.pop().unwrap().stack.is_empty())?;
70-
if !expr.labels.is_empty() {
71-
expr.pushs(results);
72-
}
73-
Ok(())
80+
fn stitch_branch<'m>(
81+
expr: &mut Expr<'_, 'm, Self>, source: SideTableBranch<'m>, target: SideTableBranch<'m>,
82+
) -> CheckResult {
83+
expr.branch_table.stitch(source, target)
7484
}
7585

76-
fn br_label<'m>(expr: &mut Expr<'_, 'm, Self>, l: LabelIdx) -> Result<ResultType<'m>, Error> {
77-
let l = l as usize;
78-
let n = expr.labels.len();
79-
check(l < n)?;
80-
let source = expr.branch_source();
81-
let label = &mut expr.labels[n - l - 1];
82-
Ok(match label.kind {
83-
LabelKind::Block | LabelKind::If(_) => {
84-
label.branches.push(source);
85-
label.type_.results
86-
}
87-
LabelKind::Loop(target) => {
88-
expr.branch_table.stitch(source, target)?;
89-
label.type_.params
90-
}
91-
})
86+
fn push_branch<'m>(
87+
branches: &mut Self::Branches<'m>, branch: SideTableBranch<'m>,
88+
) -> CheckResult {
89+
Ok(branches.push(branch))
90+
}
91+
92+
fn patch_branch<'m>(
93+
_: &Self::BranchTable<'m>, source: SideTableBranch<'m>,
94+
) -> Result<SideTableBranch<'m>, Error> {
95+
Ok(source)
9296
}
9397
}
9498

9599
#[derive(Default)]
96100
struct Verify;
97101
impl ValidMode for Verify {
98-
type LabelBranches<'m> = Option<SideTableBranch<'m>>;
99-
100-
#[allow(dead_code)]
101-
fn end_label(expr: &mut Expr<Self>) -> CheckResult {
102-
let results_len = expr.label().type_.results.len();
103-
let mut target = expr.branch_target(results_len);
104-
let label = expr.label();
105-
if let LabelKind::If(_) = label.kind {
106-
check(label.type_.params == label.type_.results)?;
107-
// SAFETY: This function is only called after parsing an End instruction.
108-
target.parser = offset_front(target.parser, -1);
109-
}
110-
if expr.label().branches.is_none_or(|x| x != target) {
111-
#[cfg(feature = "debug")]
112-
eprintln!("The side table in the custom section is wrong.");
113-
Err(unsupported(if_debug!(Unsupported::SideTable)))?
114-
}
115-
let results = expr.label().type_.results;
116-
expr.pops(results)?;
117-
check(expr.labels.pop().unwrap().stack.is_empty())?;
118-
if !expr.labels.is_empty() {
119-
expr.pushs(results);
120-
}
121-
Ok(())
102+
type Branches<'m> = Option<SideTableBranch<'m>>;
103+
type BranchTable<'m> = BranchTableView<'m>;
104+
105+
fn stitch_branch<'m>(
106+
_: &mut Expr<'_, 'm, Self>, source: SideTableBranch<'m>, target: SideTableBranch<'m>,
107+
) -> CheckResult {
108+
check(source == target)
122109
}
123110

124-
#[allow(dead_code)]
125-
fn br_label<'m>(expr: &mut Expr<'_, 'm, Self>, l: LabelIdx) -> Result<ResultType<'m>, Error> {
126-
let l = l as usize;
127-
let n = expr.labels.len();
128-
check(l < n)?;
129-
let source = expr.branch_source();
130-
// Should be `mut`.
131-
let expected_target = source;
132-
// expected_target.parser += delta_ip;
133-
// expected_target.branch_table += delta_stp;
134-
let label = &mut expr.labels[n - l - 1];
135-
Ok(match label.kind {
136-
LabelKind::Block | LabelKind::If(_) => {
137-
if !label.branches.replace(expected_target).is_none_or(|x| x == expected_target) {
138-
#[cfg(feature = "debug")]
139-
eprintln!(
140-
"The branch table entries in the custom section are consistent with each \
141-
other."
142-
);
143-
Err(unsupported(if_debug!(Unsupported::SideTable)))?
144-
}
145-
label.branches = Some(expected_target);
146-
label.type_.results
147-
}
148-
LabelKind::Loop(target) => {
149-
if expected_target != target {
150-
#[cfg(feature = "debug")]
151-
eprintln!("The branch table entries for loop in the custom section are wrong.");
152-
Err(unsupported(if_debug!(Unsupported::SideTable)))?
153-
}
154-
// expr.branch_table[source.branch_table] = the branch table entry from the custom
155-
// section;
156-
label.type_.params
157-
}
158-
})
111+
fn push_branch<'m>(
112+
branches: &mut Self::Branches<'m>, branch: SideTableBranch<'m>,
113+
) -> CheckResult {
114+
check(branches.replace(branch).is_none_or(|x| x == branch))
115+
}
116+
117+
fn patch_branch<'m>(
118+
table: &Self::BranchTable<'m>, source: SideTableBranch<'m>,
119+
) -> Result<SideTableBranch<'m>, Error> {
120+
// source.parser += delta_ip;
121+
// source.branch_table += delta_stp;
122+
todo!()
159123
}
160124
}
161125

@@ -549,7 +513,7 @@ struct Expr<'a, 'm, M: ValidMode> {
549513
is_body: bool,
550514
locals: Vec<ValType>,
551515
labels: Vec<Label<'m, M>>,
552-
branch_table: BranchTable,
516+
branch_table: M::BranchTable<'m>,
553517
}
554518

555519
#[derive(Default)]
@@ -620,7 +584,7 @@ impl BranchTable {
620584
}
621585
}
622586

623-
#[derive(Debug, Copy, Clone, PartialEq)]
587+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
624588
struct SideTableBranch<'m> {
625589
parser: &'m [u8],
626590
branch_table: usize,
@@ -636,7 +600,7 @@ struct Label<'m, M: ValidMode> {
636600
/// Whether the bottom of the stack is polymorphic.
637601
polymorphic: bool,
638602
stack: Vec<OpdType>,
639-
branches: M::LabelBranches<'m>,
603+
branches: M::Branches<'m>,
640604
/// Total stack length of the labels in this function up to this label.
641605
prev_stack: usize,
642606
}
@@ -741,7 +705,7 @@ impl<'a, 'm, M: ValidMode> Expr<'a, 'm, M> {
741705
let result = self.label().type_.results.len();
742706
let mut target = self.branch_target(result);
743707
target.branch_table += 1;
744-
self.branch_table.stitch(source, target)?
708+
M::stitch_branch(self, source, target)?;
745709
}
746710
_ => Err(invalid())?,
747711
}
@@ -1000,11 +964,45 @@ impl<'a, 'm, M: ValidMode> Expr<'a, 'm, M> {
1000964
}
1001965

1002966
fn end_label(&mut self) -> CheckResult {
1003-
M::end_label(self)
967+
let results_len = self.label().type_.results.len();
968+
let mut target = self.branch_target(results_len);
969+
for source in core::mem::take(&mut self.label().branches) {
970+
M::stitch_branch(self, source, target)?;
971+
}
972+
let label = self.label();
973+
if let LabelKind::If(source) = label.kind {
974+
check(label.type_.params == label.type_.results)?;
975+
// SAFETY: This function is only called after parsing an End instruction.
976+
target.parser = offset_front(target.parser, -1);
977+
M::stitch_branch(self, source, target)?;
978+
}
979+
let results = self.label().type_.results;
980+
self.pops(results)?;
981+
check(self.labels.pop().unwrap().stack.is_empty())?;
982+
if !self.labels.is_empty() {
983+
self.pushs(results);
984+
}
985+
Ok(())
1004986
}
1005987

1006988
fn br_label(&mut self, l: LabelIdx) -> Result<ResultType<'m>, Error> {
1007-
M::br_label(self, l)
989+
let l = l as usize;
990+
let n = self.labels.len();
991+
check(l < n)?;
992+
let source = self.branch_source();
993+
let source = M::patch_branch(&self.branch_table, source)?;
994+
let label = &mut self.labels[n - l - 1];
995+
Ok(match label.kind {
996+
LabelKind::Block | LabelKind::If(_) => {
997+
M::push_branch(&mut label.branches, source)?;
998+
label.type_.results
999+
}
1000+
LabelKind::Loop(target) => {
1001+
let params = label.type_.params;
1002+
M::stitch_branch(self, source, target)?;
1003+
params
1004+
}
1005+
})
10081006
}
10091007

10101008
fn branch_source(&mut self) -> SideTableBranch<'m> {

0 commit comments

Comments
 (0)