Skip to content
This repository was archived by the owner on Oct 3, 2025. It is now read-only.

Commit f028175

Browse files
chore: improve breaking
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
1 parent 9f82dd9 commit f028175

File tree

11 files changed

+113
-74
lines changed

11 files changed

+113
-74
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
/target
22
notes.md
33
examples/tinywasm.wat
4-
examples/wast/*
4+
examples/wast/*

.vscode/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"search.exclude": {
3+
"**/wasm-testsuite/data": true
4+
}
5+
}

crates/tinywasm/src/func.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl FuncHandle {
6767

6868
// Once the function returns:
6969
let result_m = func_ty.results.len();
70-
let res = stack.values.pop_n(result_m)?;
70+
let res = stack.values.last_n(result_m)?;
7171

7272
Ok(res
7373
.iter()

crates/tinywasm/src/runtime/executor/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ fn exec_one(
203203
panic!("Expected {} BrLabel instructions, got {}", len, instr.len());
204204
}
205205

206-
todo!()
206+
todo!("br_table");
207207
}
208208

209209
Br(v) => cf.break_to(*v, &mut stack.values)?,

crates/tinywasm/src/runtime/stack/call_stack.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,7 @@ impl CallFrame {
9797
.get_relative_to_top(break_to_relative as usize)
9898
.ok_or(Error::LabelStackUnderflow)?;
9999

100-
// trim the lable's stack from the stack
101-
value_stack.truncate_keep(break_to.stack_ptr, break_to.args.results);
100+
value_stack.break_to(break_to.stack_ptr, break_to.args.results as usize);
102101

103102
// instr_ptr points to the label instruction, but the next step
104103
// will increment it by 1 since we're changing the "current" instr_ptr

crates/tinywasm/src/runtime/stack/value_stack.rs

Lines changed: 29 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -42,31 +42,24 @@ impl ValueStack {
4242
self.top
4343
}
4444

45-
#[inline]
46-
pub(crate) fn _truncate(&mut self, n: usize) {
47-
assert!(self.top <= self.stack.len());
48-
self.top -= n;
49-
self.stack.truncate(self.top);
50-
}
51-
52-
#[inline]
53-
// example: [1, 2, 3] n=1, end_keep=1 => [1, 3]
54-
// example: [1] n=1, end_keep=1 => [1]
5545
pub(crate) fn truncate_keep(&mut self, n: usize, end_keep: usize) {
56-
if n == end_keep || n == 0 {
57-
return;
46+
let total_to_keep = n + end_keep;
47+
assert!(
48+
self.top >= total_to_keep,
49+
"Total to keep should be less than or equal to self.top"
50+
);
51+
52+
let current_size = self.stack.len();
53+
if current_size <= total_to_keep {
54+
return; // No need to truncate if the current size is already less than or equal to total_to_keep
5855
}
5956

60-
assert!(self.top <= self.stack.len());
61-
info!("removing from {} to {}", self.top - n, self.top - end_keep);
62-
self.stack.drain(self.top - n..self.top - end_keep);
63-
self.top -= n - end_keep;
64-
}
57+
let items_to_remove = current_size - total_to_keep;
58+
let remove_start_index = self.top - items_to_remove - end_keep;
59+
let remove_end_index = self.top - end_keep;
6560

66-
#[inline]
67-
pub(crate) fn _extend(&mut self, values: impl IntoIterator<Item = RawWasmValue> + ExactSizeIterator) {
68-
self.top += values.len();
69-
self.stack.extend(values);
61+
self.stack.drain(remove_start_index..remove_end_index);
62+
self.top = total_to_keep; // Update top to reflect the new size
7063
}
7164

7265
#[inline]
@@ -92,6 +85,21 @@ impl ValueStack {
9285
self.stack.pop().ok_or(Error::StackUnderflow)
9386
}
9487

88+
pub(crate) fn break_to(&mut self, new_stack_size: usize, result_count: usize) {
89+
self.stack
90+
.copy_within((self.top - result_count)..self.top, new_stack_size);
91+
self.top = new_stack_size + result_count;
92+
self.stack.truncate(self.top);
93+
}
94+
95+
#[inline]
96+
pub(crate) fn last_n(&self, n: usize) -> Result<&[RawWasmValue]> {
97+
if self.top < n {
98+
return Err(Error::StackUnderflow);
99+
}
100+
Ok(&self.stack[self.top - n..self.top])
101+
}
102+
95103
#[inline]
96104
pub(crate) fn pop_n(&mut self, n: usize) -> Result<Vec<RawWasmValue>> {
97105
if self.top < n {
@@ -120,39 +128,6 @@ impl ValueStack {
120128
#[cfg(test)]
121129
mod tests {
122130
use super::*;
123-
use crate::std::panic;
124-
125-
fn crate_stack<T: Into<RawWasmValue> + Copy>(data: &[T]) -> ValueStack {
126-
let mut stack = ValueStack::default();
127-
stack._extend(data.iter().map(|v| (*v).into()));
128-
stack
129-
}
130-
131-
fn assert_truncate_keep<T: Into<RawWasmValue> + Copy>(data: &[T], n: usize, end_keep: usize, expected: &[T]) {
132-
let mut stack = crate_stack(data);
133-
stack.truncate_keep(n, end_keep);
134-
assert_eq!(
135-
stack.data(),
136-
expected.iter().map(|v| (*v).into()).collect::<Vec<_>>().as_slice()
137-
);
138-
}
139-
140-
fn catch_unwind_silent<F: FnOnce() -> R + panic::UnwindSafe, R>(f: F) -> crate::std::thread::Result<R> {
141-
let prev_hook = panic::take_hook();
142-
panic::set_hook(alloc::boxed::Box::new(|_| {}));
143-
let result = panic::catch_unwind(f);
144-
panic::set_hook(prev_hook);
145-
result
146-
}
147-
148-
#[test]
149-
fn test_truncate_keep() {
150-
assert_truncate_keep(&[1, 2, 3], 1, 1, &[1, 2, 3]);
151-
assert_truncate_keep(&[1], 1, 1, &[1]);
152-
assert_truncate_keep(&[1, 2, 3], 2, 1, &[1, 3]);
153-
assert_truncate_keep::<i32>(&[], 0, 0, &[]);
154-
catch_unwind_silent(|| assert_truncate_keep(&[1, 2, 3], 4, 1, &[1, 3])).expect_err("should panic");
155-
}
156131

157132
#[test]
158133
fn test_value_stack() {

crates/tinywasm/src/runtime/value.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ impl RawWasmValue {
2323
ValType::I64 => WasmValue::I64(self.0 as i64),
2424
ValType::F32 => WasmValue::F32(f32::from_bits(self.0 as u32)),
2525
ValType::F64 => WasmValue::F64(f64::from_bits(self.0)),
26-
ValType::ExternRef => todo!(),
27-
ValType::FuncRef => todo!(),
28-
ValType::V128 => todo!(),
26+
ValType::ExternRef => todo!("externref"),
27+
ValType::FuncRef => todo!("funcref"),
28+
ValType::V128 => todo!("v128"),
2929
}
3030
}
3131
}

crates/tinywasm/tests/generated/mvp.csv

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
pub struct IndexMap<K, V> {
2+
map: std::collections::HashMap<K, V>,
3+
keys: Vec<K>,
4+
}
5+
6+
impl<K, V> IndexMap<K, V>
7+
where
8+
K: std::cmp::Eq + std::hash::Hash + Clone,
9+
{
10+
pub fn new() -> Self {
11+
Self {
12+
map: std::collections::HashMap::new(),
13+
keys: Vec::new(),
14+
}
15+
}
16+
17+
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
18+
if self.map.contains_key(&key) {
19+
return self.map.insert(key, value);
20+
}
21+
22+
self.keys.push(key.clone());
23+
self.map.insert(key, value)
24+
}
25+
26+
pub fn get(&self, key: &K) -> Option<&V> {
27+
self.map.get(key)
28+
}
29+
30+
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
31+
self.map.get_mut(key)
32+
}
33+
34+
pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
35+
self.keys.iter().map(move |k| (k, self.map.get(k).unwrap()))
36+
}
37+
38+
pub fn len(&self) -> usize {
39+
self.map.len()
40+
}
41+
42+
pub fn keys(&self) -> impl Iterator<Item = &K> {
43+
self.keys.iter()
44+
}
45+
46+
pub fn values(&self) -> impl Iterator<Item = &V> {
47+
self.map.values()
48+
}
49+
50+
pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
51+
self.map.values_mut()
52+
}
53+
}

crates/tinywasm/tests/testsuite/mod.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ use std::{
99
io::BufReader,
1010
};
1111

12+
mod indexmap;
1213
mod run;
1314
mod util;
1415

1516
use serde::{Deserialize, Serialize};
1617

18+
use self::indexmap::IndexMap;
19+
1720
#[derive(Serialize, Deserialize)]
1821
pub struct TestGroupResult {
1922
pub name: String,
@@ -38,14 +41,14 @@ impl TestSuite {
3841

3942
pub fn print_errors(&self) {
4043
for (group_name, group) in &self.0 {
41-
for (test_name, test) in &group.tests {
44+
let tests = &group.tests;
45+
for (test_name, test) in tests.iter() {
4246
if let Err(e) = &test.result {
4347
eprintln!(
4448
"{} {} failed: {:?}",
45-
link(
46-
format!("{}:{}", group_name.red().underline(), test.linecol.0 + 1).as_str(),
47-
format!("{}:{}", group.file, test.linecol.0 + 1).as_str()
48-
),
49+
link(group_name, &group.file, Some(test.linecol.0 + 1))
50+
.bold()
51+
.underline(),
4952
test_name.bold(),
5053
e.to_string().bright_red()
5154
);
@@ -110,8 +113,13 @@ impl TestSuite {
110113
}
111114
}
112115

113-
fn link(name: &str, file: &str) -> String {
114-
format!("\x1b]8;;file://{}\x1b\\{}\x1b]8;;\x1b\\", file, name)
116+
fn link(name: &str, file: &str, line: Option<usize>) -> String {
117+
let (path, name) = match line {
118+
None => (file.to_string(), name.to_owned()),
119+
Some(line) => (format!("{}:{}:0", file, line), (format!("{}:{}", name, line))),
120+
};
121+
122+
format!("\x1b]8;;file://{}\x1b\\{}\x1b]8;;\x1b\\", path, name)
115123
}
116124

117125
impl Debug for TestSuite {
@@ -124,7 +132,7 @@ impl Debug for TestSuite {
124132
total_passed += group_passed;
125133
total_failed += group_failed;
126134

127-
writeln!(f, "{}", link(group_name, &group.file).bold().underline())?;
135+
writeln!(f, "{}", link(group_name, &group.file, None).bold().underline())?;
128136
writeln!(f, " Tests Passed: {}", group_passed.to_string().green())?;
129137
writeln!(f, " Tests Failed: {}", group_failed.to_string().red())?;
130138

@@ -152,14 +160,14 @@ impl Debug for TestSuite {
152160
}
153161

154162
struct TestGroup {
155-
tests: BTreeMap<String, TestCase>,
163+
tests: IndexMap<String, TestCase>,
156164
file: String,
157165
}
158166

159167
impl TestGroup {
160168
fn new(file: &str) -> Self {
161169
Self {
162-
tests: BTreeMap::new(),
170+
tests: IndexMap::new(),
163171
file: file.to_string(),
164172
}
165173
}

0 commit comments

Comments
 (0)