Skip to content

Commit 72e7cf5

Browse files
cemonemwucke13
authored andcommitted
docs: light documentation for validation stack methods
Signed-off-by: Cem Onem <cem.oenem@dlr.de>
1 parent bdf7dfc commit 72e7cf5

File tree

2 files changed

+72
-27
lines changed

2 files changed

+72
-27
lines changed

src/validation/code.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ fn read_instructions(
229229
let label_info = LabelInfo::Block {
230230
stps_to_backpatch: Vec::new(),
231231
};
232+
// The types are explicitly popped and pushed in
233+
// https://webassembly.github.io/spec/core/appendix/algorithm.html
234+
// therefore types on the stack might change.
232235
stack.assert_push_ctrl(label_info, block_ty, true)?;
233236
}
234237
LOOP => {
@@ -237,6 +240,9 @@ fn read_instructions(
237240
ip: wasm.pc,
238241
stp: sidetable.len(),
239242
};
243+
// The types are explicitly popped and pushed in
244+
// https://webassembly.github.io/spec/core/appendix/algorithm.html
245+
// therefore types on the stack might change.
240246
stack.assert_push_ctrl(label_info, block_ty, true)?;
241247
}
242248
IF => {
@@ -256,6 +262,9 @@ fn read_instructions(
256262
stp: stp_here,
257263
stps_to_backpatch: Vec::new(),
258264
};
265+
// The types are explicitly popped and pushed in
266+
// https://webassembly.github.io/spec/core/appendix/algorithm.html
267+
// therefore types on the stack might change.
259268
stack.assert_push_ctrl(label_info, block_ty, true)?;
260269
}
261270
ELSE => {
@@ -291,7 +300,9 @@ fn read_instructions(
291300
for valtype in block_ty.params.valtypes.iter() {
292301
stack.push_valtype(*valtype);
293302
}
294-
303+
// The types are explicitly popped and pushed in
304+
// https://webassembly.github.io/spec/core/appendix/algorithm.html
305+
// therefore types on the stack might change.
295306
stack.assert_push_ctrl(label_info, block_ty, true)?;
296307
} else {
297308
return Err(Error::ElseWithoutMatchingIf);
@@ -307,6 +318,9 @@ fn read_instructions(
307318
BR_IF => {
308319
let label_idx = wasm.read_var_u32()? as LabelIdx;
309320
stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
321+
// The types are explicitly popped and pushed in
322+
// https://webassembly.github.io/spec/core/appendix/algorithm.html
323+
// therefore types on the stack might change.
310324
validate_intrablock_jump_and_generate_sidetable_entry(
311325
wasm, label_idx, stack, sidetable, true,
312326
)?;
@@ -356,6 +370,9 @@ fn read_instructions(
356370
stack.make_unspecified()?;
357371
}
358372
END => {
373+
// The types are explicitly popped and pushed in
374+
// https://webassembly.github.io/spec/core/appendix/algorithm.html
375+
// therefore types on the stack might change.
359376
let (label_info, block_ty) = stack.assert_pop_ctrl(true)?;
360377
let stp_here = sidetable.len();
361378

src/validation/validation_stack.rs

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub struct ValidationStack {
1717
}
1818

1919
impl ValidationStack {
20-
/// Initialize a new ValidationStack
20+
/// Initialize a new ValidationStack to validate a block of type [] -> []
2121
pub fn new() -> Self {
2222
Self {
2323
stack: Vec::new(),
@@ -37,6 +37,7 @@ impl ValidationStack {
3737
}
3838
}
3939

40+
/// Initialize a new ValidationStack to validate a block of type `block_ty`
4041
pub(super) fn new_for_func(block_ty: FuncType) -> Self {
4142
Self {
4243
stack: Vec::new(),
@@ -71,6 +72,12 @@ impl ValidationStack {
7172
Ok(())
7273
}
7374

75+
/// Mark the current control block as unreachable, removing all of the types pushed to the stack since the current control block was entered.
76+
/// pop operations from the stack will yield `Ok(ValidationStackEntry::Bottom)` if the stack height is the same as the height when this control
77+
/// block was entered.
78+
///
79+
/// Returns `Ok(())` if called during validation of a control block. `Returns Err(Error::ValidationCtrlStackEmpty)` if no control block context is found
80+
/// in the control block stack.
7481
pub(super) fn make_unspecified(&mut self) -> Result<()> {
7582
let last_ctrl_stack_entry = self
7683
.ctrl_stack
@@ -86,8 +93,9 @@ impl ValidationStack {
8693
/// # Returns
8794
///
8895
/// - Returns `Ok(_)` with the former top-most [`ValidationStackEntry`] inside, if the stack had
89-
/// at least one element.
90-
/// - Returns `Err(_)` if the stack was already empty.
96+
/// at least one element pushed after the current control block is entered. May also return `Ok(ValidationStackEntry::Bottom)`
97+
/// if `make_unspecified` is called within the current control block.
98+
/// - Returns `Err(_)` otherwise.
9199
fn pop_valtype(&mut self) -> Result<ValidationStackEntry> {
92100
// TODO unwrapping might not be the best option
93101
// TODO ugly
@@ -106,6 +114,11 @@ impl ValidationStack {
106114
}
107115
}
108116

117+
/// Attempt popping `Valtype::RefType(expected_ty)` from type stack.
118+
///
119+
/// # Returns
120+
///
121+
/// - Returns `Ok(())` if `Valtype::RefType(expected_ty)` unifies to the item returned by `pop_valtype` operation and `Err(_)` otherwise.
109122
pub fn assert_pop_ref_type(&mut self, expected_ty: Option<RefType>) -> Result<()> {
110123
match self.pop_valtype()? {
111124
ValidationStackEntry::Val(ValType::RefType(ref_type)) => {
@@ -120,15 +133,11 @@ impl ValidationStack {
120133
}
121134
}
122135

123-
/// Assert the top-most [`ValidationStackEntry`] is a specific [`ValType`], after popping it from the [`ValidationStack`]
124-
/// This assertion will unify the the top-most entry with `expected_ty`.
136+
/// Attempt popping expected_ty from type stack.
125137
///
126138
/// # Returns
127139
///
128-
/// - Returns `Ok(())` if the top-most [`ValidationStackEntry`] is a [`ValType`] identical to
129-
/// `expected_ty`.
130-
/// - Returns `Err(_)` otherwise.
131-
///
140+
/// - Returns `Ok(())` if expected_ty unifies to the item returned by `pop_valtype` operation and `Err(_)` otherwise.
132141
pub fn assert_pop_val_type(&mut self, expected_ty: ValType) -> Result<()> {
133142
match self.pop_valtype()? {
134143
ValidationStackEntry::Val(ty) => (ty == expected_ty)
@@ -215,19 +224,15 @@ impl ValidationStack {
215224
Err(Error::EndInvalidValueStack)
216225
}
217226
}
218-
/// Asserts that the values on top of the stack match those of a value iterator
219-
/// This method will unify the types on the stack to the expected valtypes.
220-
/// The last element of `expected_val_types` is unified to the top-most
221-
/// [`ValidationStackEntry`], the second last `expected_val_types` element to the second top-most
222-
/// [`ValidationStackEntry`] etc.
223-
///
224-
/// Any unification failure or arity mismatch will cause an error.
225-
///
227+
228+
/// Assert that the types retrieved from the type stack by `pop_valtype` unify to `expected_val_types`, and
229+
/// after this operation the type stack would be the same as the first time the current control block is entered.
230+
/// This method will unify the types on the stack to the expected valtypes if `unify_to_expected_types` is set.
226231
/// Any occurence of an error may leave the stack in an invalid state.
227232
///
228233
/// # Returns
229234
///
230-
/// - `Ok(_)`, the tail of the stack matches the `expected_val_types`
235+
/// - `Ok(_)`, the tail of the stack unifies to the `expected_val_types`
231236
/// - `Err(_)` otherwise
232237
///
233238
pub(super) fn assert_val_types_on_top(
@@ -243,16 +248,15 @@ impl ValidationStack {
243248
)
244249
}
245250

246-
// TODO better documentation
247-
/// Asserts that the valtypes on the stack match the expected valtypes and no other type is on the stack.
248-
/// This method will unify the types on the stack to the expected valtypes.
249-
/// This starts by comparing the top-most valtype with the last element from `expected_val_types` and then continues downwards on the stack.
250-
/// If a label is reached and not all `expected_val_types` have been checked, the assertion fails.
251+
/// Assert that the types retrieved from the type stack by `pop_valtype` unify to `expected_val_types`.
252+
/// This method will unify the types on the stack to the expected valtypes if `unify_to_expected_types` is set.
253+
/// Any occurence of an error may leave the stack in an invalid state.
251254
///
252255
/// # Returns
253256
///
254-
/// - `Ok(())` if all expected valtypes were found
257+
/// - `Ok(_)`, the tail of the stack unifies to the `expected_val_types`
255258
/// - `Err(_)` otherwise
259+
///
256260
pub fn assert_val_types(
257261
&mut self,
258262
expected_val_types: &[ValType],
@@ -266,6 +270,15 @@ impl ValidationStack {
266270
)
267271
}
268272

273+
/// Call `assert_val_types_on_top` for the label signature of the `label_idx`th outer control block (0 corresponds to the current control block).
274+
/// Label signature of all controi blocks are the output signature of the control blocks except for the Loop block. For Loop blocks, it is the input signature.
275+
/// This method will unify the types on the stack to the expected valtypes if `unify_to_expected_types` is set.
276+
///
277+
/// # Returns
278+
///
279+
/// - `Ok(_)`, the tail of the stack unifies to the label signature of the `label_idx`th outer control block
280+
/// - `Err(_)` otherwise
281+
///
269282
pub fn assert_val_types_of_label_jump_types_on_top(
270283
&mut self,
271284
label_idx: usize,
@@ -284,6 +297,14 @@ impl ValidationStack {
284297
)
285298
}
286299

300+
/// Signal to this struct that a new control block is entered, and calls `assert_val_types_on_top` with the input signature of the new control block.
301+
/// This method will unify the types on the stack to the expected valtypes if `unify_to_expected_types` is set.
302+
///
303+
/// # Returns
304+
///
305+
/// - `Ok(_)`, the tail of the stack unifies to the input signature of the new control block
306+
/// - `Err(_)` otherwise
307+
///
287308
pub fn assert_push_ctrl(
288309
&mut self,
289310
label_info: LabelInfo,
@@ -301,8 +322,14 @@ impl ValidationStack {
301322
Ok(())
302323
}
303324

304-
// TODO: rename/refactor this function to make it more clear that it ALSO
305-
// checks the stack for valid return types.
325+
/// Signal to this struct that the current control block is exited, and calls `assert_val_types_on_top` with the output signature of the new control block.
326+
/// This method will unify the types on the stack to the expected valtypes if `unify_to_expected_types` is set.
327+
///
328+
/// # Returns
329+
///
330+
/// - `Ok(_)`, the tail of the stack unifies to the output signature of the current control block
331+
/// - `Err(_)` otherwise
332+
///
306333
pub fn assert_pop_ctrl(
307334
&mut self,
308335
unify_to_expected_types: bool,
@@ -329,6 +356,7 @@ impl ValidationStack {
329356
))
330357
}
331358

359+
/// Validate the `SELECT` instruction within the current control block. Returns OK(()) on success, Err(_) otherwise.
332360
pub fn validate_polymorphic_select(&mut self) -> Result<()> {
333361
//SELECT instruction has the type signature
334362
//[t t i32] -> [t] where t unifies to a NumType(_) or VecType

0 commit comments

Comments
 (0)