11use crate :: ParserOptions ;
22use alloc:: vec:: Vec ;
3- use tinywasm_types:: Instruction ;
3+ use tinywasm_types:: { Instruction , WasmFunctionData } ;
44
55pub ( 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
0 commit comments