(
instrs: &mut [Instruction],
function_results: ValueCounts,
self_func_addr: u32,
imported_memory_count: u32,
)
| 29 | } |
| 30 | |
| 31 | fn rewrite( |
| 32 | instrs: &mut [Instruction], |
| 33 | function_results: ValueCounts, |
| 34 | self_func_addr: u32, |
| 35 | imported_memory_count: u32, |
| 36 | ) -> bool { |
| 37 | use Instruction::*; |
| 38 | let mut uses_local_memory = false; |
| 39 | let return_instr = match function_results { |
| 40 | ValueCounts { c32: 0, c64: 0, c128: 0 } => Some(ReturnVoid), |
| 41 | ValueCounts { c32: 1, c64: 0, c128: 0 } => Some(Return32), |
| 42 | ValueCounts { c32: 0, c64: 1, c128: 0 } => Some(Return64), |
| 43 | ValueCounts { c32: 0, c64: 0, c128: 1 } => Some(Return128), |
| 44 | _ => None, |
| 45 | }; |
| 46 | |
| 47 | for i in 0..instrs.len() { |
| 48 | match instrs[i] { |
| 49 | LocalCopy32(a, b) if a == b => instrs[i] = Nop, |
| 50 | LocalCopy64(a, b) if a == b => instrs[i] = Nop, |
| 51 | LocalCopy128(a, b) if a == b => instrs[i] = Nop, |
| 52 | Call(addr) if addr == self_func_addr => instrs[i] = CallSelf, |
| 53 | ReturnCall(addr) if addr == self_func_addr => instrs[i] = ReturnCallSelf, |
| 54 | Return if let Some(return_instr) = return_instr => instrs[i] = return_instr, |
| 55 | instr @ (I32Add | I32Mul | I32And | I32Or | I32Xor) => { |
| 56 | let Some(op) = int_bin_op_32(instr) else { unreachable!() }; |
| 57 | rewrite!(instrs, i, [LocalGet32(a), LocalGet32(b)] => BinOpLocalLocal32(op, a, b)); |
| 58 | rewrite!(instrs, i, [LocalGet32(local), Const32(c)] => BinOpLocalConst32(op, local, c)); |
| 59 | rewrite!(instrs, i, [Const32(c), LocalGet32(local)] => BinOpLocalConst32(op, local, c)); |
| 60 | rewrite!(instrs, i, [GlobalGet(global)] => [Nop, BinOpStackGlobal32(op, global)]); |
| 61 | if matches!(op, BinOp::IAdd) { |
| 62 | rewrite!(instrs, i, [Const32(c)] => AddConst32(c)); |
| 63 | rewrite!(instrs, i, [I32Add] => [Nop, I32Add3]); |
| 64 | } |
| 65 | } |
| 66 | instr @ (I32Sub | I32Shl | I32ShrS | I32ShrU | I32Rotl | I32Rotr) => { |
| 67 | let Some(op) = int_bin_op_32(instr) else { unreachable!() }; |
| 68 | rewrite!(instrs, i, [LocalGet32(a), LocalGet32(b)] => BinOpLocalLocal32(op, a, b)); |
| 69 | rewrite!(instrs, i, [LocalGet32(local), Const32(c)] => BinOpLocalConst32(op, local, c)); |
| 70 | rewrite!(instrs, i, [GlobalGet(global)] => [Nop, BinOpStackGlobal32(op, global)]); |
| 71 | if matches!(op, BinOp::IShrS) { |
| 72 | rewrite!(instrs, i, [BinOpLocalConst32(BinOp::IShl, local, 8), Const32(8)] => [Nop, LocalGet32(local), I32Extend8S]); |
| 73 | rewrite!(instrs, i, [BinOpLocalConst32(BinOp::IShl, local, 16), Const32(16)] => [Nop, LocalGet32(local), I32Extend16S]); |
| 74 | } |
| 75 | } |
| 76 | instr @ (I64Add | I64Mul | I64And | I64Or | I64Xor) => { |
| 77 | let Some(op) = int_bin_op_64(instr) else { unreachable!() }; |
| 78 | rewrite!(instrs, i, [LocalGet64(a), LocalGet64(b)] => BinOpLocalLocal64(op, a, b)); |
| 79 | rewrite!(instrs, i, [LocalGet64(local), Const64(c)] => BinOpLocalConst64(op, local, c)); |
| 80 | rewrite!(instrs, i, [Const64(c), LocalGet64(local)] => BinOpLocalConst64(op, local, c)); |
| 81 | rewrite!(instrs, i, [GlobalGet(global)] => [Nop, BinOpStackGlobal64(op, global)]); |
| 82 | if matches!(op, BinOp::IAdd) { |
| 83 | rewrite!(instrs, i, [Const64(c)] => AddConst64(c)); |
| 84 | rewrite!(instrs, i, [I64Add] => [Nop, I64Add3]); |
| 85 | } |
| 86 | } |
| 87 | instr @ (I64Sub | I64Shl | I64ShrS | I64ShrU | I64Rotl | I64Rotr) => { |
| 88 | let Some(op) = int_bin_op_64(instr) else { unreachable!() }; |
no test coverage detected