Skip to content

Commit 66c9f7a

Browse files
chore: fix stable build, move BranchTableTarget to FunctionData
Signed-off-by: Henry <mail@henrygressmann.de>
1 parent 786152d commit 66c9f7a

File tree

6 files changed

+114
-100
lines changed

6 files changed

+114
-100
lines changed

crates/parser/src/module.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ impl ModuleReader {
196196
.into_iter()
197197
.zip(self.code_type_addrs)
198198
.enumerate()
199-
.map(|(func_idx, ((instructions, data, locals), ty_idx))| {
199+
.map(|(func_idx, ((instructions, mut data, locals), ty_idx))| {
200200
let ty = self.func_types.get(ty_idx as usize).expect("No func type for func, this is a bug").clone();
201201
let params = ValueCountsSmall::from(&ty.params);
202202
let locals = ValueCountsSmall {
@@ -206,7 +206,7 @@ impl ModuleReader {
206206
cref: u16::try_from(locals.cref).unwrap_or_else(|_| unreachable!("local count exceeds u16")),
207207
};
208208
let self_func_addr = imported_func_count + func_idx as u32;
209-
let instructions = optimize::optimize_instructions(instructions, self_func_addr, options);
209+
let instructions = optimize::optimize_instructions(instructions, &mut data, self_func_addr, options);
210210

211211
WasmFunction { instructions: ArcSlice::from(instructions), data, locals, params, ty }
212212
})

crates/parser/src/optimize.rs

Lines changed: 80 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
use crate::ParserOptions;
22
use alloc::vec::Vec;
3-
use tinywasm_types::Instruction;
3+
use tinywasm_types::{Instruction, WasmFunctionData};
44

55
pub(crate) fn optimize_instructions(
66
mut instructions: Vec<Instruction>,
7+
function_data: &mut WasmFunctionData,
78
self_func_addr: u32,
89
options: &ParserOptions,
910
) -> Vec<Instruction> {
1011
rewrite(&mut instructions, self_func_addr);
1112
if options.dce {
12-
dce(&mut instructions);
13+
dce(&mut instructions, function_data);
1314
}
1415
instructions
1516
}
@@ -135,29 +136,32 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
135136
instructions[read] = Instruction::Nop;
136137
}
137138
}
138-
Instruction::LocalGet64(dst)
139+
Instruction::LocalGet64(dst) => {
139140
if read > 0
140141
&& let Instruction::LocalSet64(src) = instructions[read - 1]
141-
&& src == dst =>
142-
{
143-
instructions[read - 1] = Instruction::LocalTee64(src);
144-
instructions[read] = Instruction::Nop;
142+
&& src == dst
143+
{
144+
instructions[read - 1] = Instruction::LocalTee64(src);
145+
instructions[read] = Instruction::Nop;
146+
}
145147
}
146-
Instruction::LocalGet128(dst)
148+
Instruction::LocalGet128(dst) => {
147149
if read > 0
148150
&& let Instruction::LocalSet128(src) = instructions[read - 1]
149-
&& src == dst =>
150-
{
151-
instructions[read - 1] = Instruction::LocalTee128(src);
152-
instructions[read] = Instruction::Nop;
151+
&& src == dst
152+
{
153+
instructions[read - 1] = Instruction::LocalTee128(src);
154+
instructions[read] = Instruction::Nop;
155+
}
153156
}
154-
Instruction::LocalGetRef(dst)
157+
Instruction::LocalGetRef(dst) => {
155158
if read > 0
156159
&& let Instruction::LocalSetRef(src) = instructions[read - 1]
157-
&& src == dst =>
158-
{
159-
instructions[read - 1] = Instruction::LocalTeeRef(src);
160-
instructions[read] = Instruction::Nop;
160+
&& src == dst
161+
{
162+
instructions[read - 1] = Instruction::LocalTeeRef(src);
163+
instructions[read] = Instruction::Nop;
164+
}
161165
}
162166

163167
Instruction::LocalSet32(dst) => {
@@ -230,19 +234,23 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
230234
instructions[read] = Instruction::LocalAddConst64(dst, c);
231235
}
232236
}
233-
Instruction::LocalSet128(dst)
237+
Instruction::LocalSet128(dst) => {
234238
if read > 0
235-
&& let Instruction::LocalGet128(src) = instructions[read - 1] =>
236-
{
237-
instructions[read - 1] = Instruction::Nop;
238-
instructions[read] = if src == dst { Instruction::Nop } else { Instruction::LocalCopy128(src, dst) };
239+
&& let Instruction::LocalGet128(src) = instructions[read - 1]
240+
{
241+
instructions[read - 1] = Instruction::Nop;
242+
instructions[read] =
243+
if src == dst { Instruction::Nop } else { Instruction::LocalCopy128(src, dst) };
244+
}
239245
}
240-
Instruction::LocalSetRef(dst)
246+
Instruction::LocalSetRef(dst) => {
241247
if read > 0
242-
&& let Instruction::LocalGetRef(src) = instructions[read - 1] =>
243-
{
244-
instructions[read - 1] = Instruction::Nop;
245-
instructions[read] = if src == dst { Instruction::Nop } else { Instruction::LocalCopyRef(src, dst) };
248+
&& let Instruction::LocalGetRef(src) = instructions[read - 1]
249+
{
250+
instructions[read - 1] = Instruction::Nop;
251+
instructions[read] =
252+
if src == dst { Instruction::Nop } else { Instruction::LocalCopyRef(src, dst) };
253+
}
246254
}
247255

248256
Instruction::LocalTee32(dst) => {
@@ -273,55 +281,61 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
273281
}
274282
_ => {}
275283
},
276-
Instruction::LocalTee128(dst)
284+
Instruction::LocalTee128(dst) => {
277285
if read > 0
278286
&& let Instruction::LocalGet128(src) = instructions[read - 1]
279-
&& src == dst =>
280-
{
281-
instructions[read] = Instruction::Nop;
287+
&& src == dst
288+
{
289+
instructions[read] = Instruction::Nop;
290+
}
282291
}
283-
Instruction::LocalTeeRef(dst)
292+
Instruction::LocalTeeRef(dst) => {
284293
if read > 0
285294
&& let Instruction::LocalGetRef(src) = instructions[read - 1]
286-
&& src == dst =>
287-
{
288-
instructions[read] = Instruction::Nop;
295+
&& src == dst
296+
{
297+
instructions[read] = Instruction::Nop;
298+
}
289299
}
290300

291-
Instruction::Drop32
301+
Instruction::Drop32 => {
292302
if read > 0
293-
&& let Instruction::LocalTee32(local) = instructions[read - 1] =>
294-
{
295-
instructions[read - 1] = Instruction::LocalSet32(local);
296-
instructions[read] = Instruction::Nop;
303+
&& let Instruction::LocalTee32(local) = instructions[read - 1]
304+
{
305+
instructions[read - 1] = Instruction::LocalSet32(local);
306+
instructions[read] = Instruction::Nop;
307+
}
297308
}
298-
Instruction::Drop64
309+
Instruction::Drop64 => {
299310
if read > 0
300-
&& let Instruction::LocalTee64(local) = instructions[read - 1] =>
301-
{
302-
instructions[read - 1] = Instruction::LocalSet64(local);
303-
instructions[read] = Instruction::Nop;
311+
&& let Instruction::LocalTee64(local) = instructions[read - 1]
312+
{
313+
instructions[read - 1] = Instruction::LocalSet64(local);
314+
instructions[read] = Instruction::Nop;
315+
}
304316
}
305-
Instruction::Drop128
317+
Instruction::Drop128 => {
306318
if read > 0
307-
&& let Instruction::LocalTee128(local) = instructions[read - 1] =>
308-
{
309-
instructions[read - 1] = Instruction::LocalSet128(local);
310-
instructions[read] = Instruction::Nop;
319+
&& let Instruction::LocalTee128(local) = instructions[read - 1]
320+
{
321+
instructions[read - 1] = Instruction::LocalSet128(local);
322+
instructions[read] = Instruction::Nop;
323+
}
311324
}
312-
Instruction::DropRef
325+
Instruction::DropRef => {
313326
if read > 0
314-
&& let Instruction::LocalTeeRef(local) = instructions[read - 1] =>
315-
{
316-
instructions[read - 1] = Instruction::LocalSetRef(local);
317-
instructions[read] = Instruction::Nop;
327+
&& let Instruction::LocalTeeRef(local) = instructions[read - 1]
328+
{
329+
instructions[read - 1] = Instruction::LocalSetRef(local);
330+
instructions[read] = Instruction::Nop;
331+
}
318332
}
319333
_ => {}
320334
}
321335
}
322336
}
323337

324-
fn dce(instructions: &mut Vec<Instruction>) {
338+
fn dce(instructions: &mut Vec<Instruction>, function_data: &mut WasmFunctionData) {
325339
let old_len = instructions.len();
326340
if old_len == 0 {
327341
return;
@@ -340,13 +354,21 @@ fn dce(instructions: &mut Vec<Instruction>) {
340354
}
341355

342356
let compacted_len = old_len as u32 - removed_total;
357+
358+
function_data.branch_table_targets.iter_mut().for_each(|ip| {
359+
let old_target = *ip as usize;
360+
if old_target <= old_len {
361+
*ip -= removed_before[old_target];
362+
debug_assert!(*ip < compacted_len, "remapped jump target points past end of function");
363+
}
364+
});
365+
343366
instructions.retain_mut(|instr| {
344367
let ip = match instr {
345368
Instruction::Jump(ip)
346369
| Instruction::JumpIfZero(ip)
347370
| Instruction::JumpIfNonZero(ip)
348-
| Instruction::BranchTableTarget(ip)
349-
| Instruction::BranchTable(ip, _) => ip,
371+
| Instruction::BranchTable(ip, _, _) => ip,
350372
_ => return !matches!(instr, Instruction::Nop),
351373
};
352374

crates/parser/src/visit.rs

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,21 @@ struct LoweringCtx {
3232
branch_jumps: Vec<usize>,
3333
}
3434

35+
#[derive(Default)]
36+
struct FunctionDataBuilder {
37+
v128_constants: Vec<i128>,
38+
branch_table_targets: Vec<u32>,
39+
}
40+
41+
impl FunctionDataBuilder {
42+
fn finish(self) -> WasmFunctionData {
43+
WasmFunctionData {
44+
v128_constants: self.v128_constants.into_boxed_slice(),
45+
branch_table_targets: self.branch_table_targets.into_boxed_slice(),
46+
}
47+
}
48+
}
49+
3550
struct ValidateThenVisit<'a, R: WasmModuleResources>(usize, &'a mut FunctionBuilder<R>);
3651

3752
macro_rules! validate_then_visit {
@@ -75,11 +90,7 @@ pub(crate) fn process_operators_and_validate<R: WasmModuleResources>(
7590
return Err(builder.errors.remove(0));
7691
}
7792

78-
Ok((
79-
builder.instructions,
80-
WasmFunctionData { v128_constants: builder.v128_constants.into_boxed_slice() },
81-
builder.validator.into_allocations(),
82-
))
93+
Ok((builder.instructions, builder.data.finish(), builder.validator.into_allocations()))
8394
}
8495

8596
macro_rules! define_operand {
@@ -135,7 +146,7 @@ macro_rules! define_mem_operands_simd_lane {
135146
pub(crate) struct FunctionBuilder<R: WasmModuleResources> {
136147
validator: FuncValidator<R>,
137148
instructions: Vec<Instruction>,
138-
v128_constants: Vec<i128>,
149+
data: FunctionDataBuilder,
139150
ctx_stack: Vec<LoweringCtx>,
140151
local_addr_map: Vec<u32>,
141152
errors: Vec<crate::ParseError>,
@@ -390,14 +401,8 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
390401
let target_depths: Vec<u32> = ts;
391402

392403
let header_ip = self.instructions.len();
393-
self.instructions.push(Instruction::BranchTable(0, len));
394-
395-
let target_table_ip = self.instructions.len();
396-
for _ in 0..len {
397-
self.instructions.push(Instruction::BranchTableTarget(0));
398-
}
399-
let default_target_ip = self.instructions.len();
400-
self.instructions.push(Instruction::BranchTableTarget(0));
404+
let branch_table_start = self.data.branch_table_targets.len() as u32;
405+
self.instructions.push(Instruction::BranchTable(0, branch_table_start, len));
401406

402407
let mut seen = alloc::collections::BTreeMap::<u32, usize>::new();
403408
struct PadInfo {
@@ -418,18 +423,13 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
418423
pads.push(PadInfo { depth, pad_start, jump_or_ret_ip, is_return });
419424
}
420425

421-
for (i, &depth) in target_depths.iter().enumerate() {
426+
for &depth in &target_depths {
422427
let pad_idx = seen[&depth];
423-
if let Instruction::BranchTableTarget(ip) = &mut self.instructions[target_table_ip + i] {
424-
*ip = pads[pad_idx].pad_start as u32;
425-
}
428+
self.data.branch_table_targets.push(pads[pad_idx].pad_start as u32);
426429
}
427430

428431
let default_pad_idx = seen[&default_depth];
429-
if let Instruction::BranchTableTarget(ip) = &mut self.instructions[default_target_ip] {
430-
*ip = pads[default_pad_idx].pad_start as u32;
431-
}
432-
if let Instruction::BranchTable(default_ip, _) = &mut self.instructions[header_ip] {
432+
if let Instruction::BranchTable(default_ip, _, _) = &mut self.instructions[header_ip] {
433433
*default_ip = pads[default_pad_idx].pad_start as u32;
434434
}
435435

@@ -570,13 +570,13 @@ impl<R: WasmModuleResources> wasmparser::VisitSimdOperator<'_> for FunctionBuild
570570
}
571571

572572
fn visit_i8x16_shuffle(&mut self, lanes: [u8; 16]) -> Self::Output {
573-
self.instructions.push(Instruction::I8x16Shuffle(self.v128_constants.len() as u32));
574-
self.v128_constants.push(i128::from_le_bytes(lanes));
573+
self.instructions.push(Instruction::I8x16Shuffle(self.data.v128_constants.len() as u32));
574+
self.data.v128_constants.push(i128::from_le_bytes(lanes));
575575
}
576576

577577
fn visit_v128_const(&mut self, value: wasmparser::V128) -> Self::Output {
578-
self.instructions.push(Instruction::V128Const(self.v128_constants.len() as u32));
579-
self.v128_constants.push(value.i128());
578+
self.instructions.push(Instruction::V128Const(self.data.v128_constants.len() as u32));
579+
self.data.v128_constants.push(value.i128());
580580
}
581581
}
582582

@@ -593,7 +593,7 @@ impl<R: WasmModuleResources> FunctionBuilder<R> {
593593
validator,
594594
local_addr_map,
595595
instructions: Vec::with_capacity(instr_capacity),
596-
v128_constants: Vec::new(),
596+
data: FunctionDataBuilder::default(),
597597
ctx_stack: Vec::with_capacity(256),
598598
errors: Vec::new(),
599599
}

crates/tinywasm/src/interpreter/executor.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,7 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
154154
let k = *keep as usize;
155155
self.store.stack.values.stack_ref.truncate_keep(b as usize, k);
156156
}
157-
BranchTable(default_ip, len) => { self.exec_branch_table(*default_ip, *len); continue; }
158-
BranchTableTarget {..} => {},
157+
BranchTable(default_ip, start, len) => { self.exec_branch_table(*default_ip, *start, *len); continue; }
159158
Return => { if self.exec_return() { return Ok(Some(())); } continue; }
160159
LocalGet32(local_index) => self.store.stack.values.push(self.store.stack.values.local_get::<Value32>(&self.cf, *local_index))?,
161160
LocalGet64(local_index) => self.store.stack.values.push(self.store.stack.values.local_get::<Value64>(&self.cf, *local_index))?,
@@ -696,15 +695,10 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
696695
}
697696

698697
#[inline(always)]
699-
fn exec_branch_table(&mut self, default_ip: u32, len: u32) {
698+
fn exec_branch_table(&mut self, default_ip: u32, start: u32, len: u32) {
700699
let idx = self.store.stack.values.pop::<i32>();
701-
let start = self.cf.instr_ptr + 1;
702-
703700
let target_ip = if idx >= 0 && (idx as u32) < len {
704-
match self.func.instructions.0.get((start + idx as u32) as usize) {
705-
Some(Instruction::BranchTableTarget(ip)) => *ip,
706-
_ => default_ip,
707-
}
701+
self.func.data.branch_table_targets.get((start + idx as u32) as usize).copied().unwrap_or(default_ip)
708702
} else {
709703
default_ip
710704
};

crates/types/src/instructions.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ pub enum Instruction {
7777
DropKeep64(u16, u16),
7878
DropKeep128(u16, u16),
7979
DropKeepRef(u16, u16),
80-
BranchTable(u32, u32), // (default_landing_pad_ip, target_count) - followed by BranchTableTarget entries
81-
BranchTableTarget(u32), // (landing_pad_ip)
80+
BranchTable(u32, u32, u32), // (default_landing_pad_ip, branch_table_start, target_count)
8281
Return,
8382
Call(FuncAddr),
8483
CallSelf,
@@ -164,8 +163,6 @@ pub enum Instruction {
164163
F32ConvertI32S, F32ConvertI32U, F32ConvertI64S, F32ConvertI64U, F32DemoteF64,
165164
F64ConvertI32S, F64ConvertI32U, F64ConvertI64S, F64ConvertI64U, F64PromoteF32,
166165

167-
// Reinterpretations are parser no-ops and intentionally omitted.
168-
169166
// Saturating Float-to-Int Conversions
170167
I32TruncSatF32S, I32TruncSatF32U, I32TruncSatF64S, I32TruncSatF64U,
171168
I64TruncSatF32S, I64TruncSatF32U, I64TruncSatF64S, I64TruncSatF64U,

crates/types/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for ArcSlice<T> {
318318
#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
319319
pub struct WasmFunctionData {
320320
pub v128_constants: Box<[i128]>,
321+
pub branch_table_targets: Box<[u32]>,
321322
}
322323

323324
/// A WebAssembly Module Export

0 commit comments

Comments
 (0)