If the results on the stack are handled via the stack pointer, ensure that the stack results are correctly located. In general, since values in the value stack are spilled when exiting the block, the top `n` entries in the value stack, representing the `n` stack results of the block are almost correctly located. However, since constants are not spilled, their presence complicate block exits. For t
(
ret_area: RetArea,
results: &ABIResults,
context: &mut CodeGenContext<Emission>,
masm: &mut M,
)
| 834 | // SpiderMonkey's WebAssembly Baseline Compiler: |
| 835 | // https://wingolog.org/archives/2020/04/03/multi-value-webassembly-in-firefox-from-1-to-n |
| 836 | fn adjust_stack_results<M>( |
| 837 | ret_area: RetArea, |
| 838 | results: &ABIResults, |
| 839 | context: &mut CodeGenContext<Emission>, |
| 840 | masm: &mut M, |
| 841 | ) -> Result<()> |
| 842 | where |
| 843 | M: MacroAssembler, |
| 844 | { |
| 845 | ensure!(ret_area.is_sp(), CodeGenError::sp_addressing_expected()); |
| 846 | let results_offset = ret_area.unwrap_sp(); |
| 847 | |
| 848 | // Start iterating from memory values that are closer to the |
| 849 | // frame pointer (oldest entries first). |
| 850 | for (i, operand) in results.operands().iter().enumerate() { |
| 851 | if operand.is_reg() { |
| 852 | break; |
| 853 | } |
| 854 | |
| 855 | let value_index = (context.stack.len() - results.stack_operands_len()) + i; |
| 856 | let val = context.stack.inner()[value_index]; |
| 857 | |
| 858 | match (val, operand) { |
| 859 | (Val::Memory(mem), ABIOperand::Stack { offset, size, .. }) => { |
| 860 | let dst = results_offset.as_u32() - *offset; |
| 861 | let src = mem.slot.offset; |
| 862 | |
| 863 | // Values are moved from lower (SP) to higher (FP) |
| 864 | // addresses. |
| 865 | if src.as_u32() <= dst { |
| 866 | break; |
| 867 | } |
| 868 | |
| 869 | masm.memmove( |
| 870 | src, |
| 871 | SPOffset::from_u32(dst), |
| 872 | *size, |
| 873 | MemMoveDirection::LowToHigh, |
| 874 | )?; |
| 875 | } |
| 876 | _ => {} |
| 877 | } |
| 878 | } |
| 879 | |
| 880 | // Start iterating from memory values that are closer to the |
| 881 | // stack pointer (newest entries first). |
| 882 | for (i, operand) in results |
| 883 | .operands() |
| 884 | .iter() |
| 885 | .rev() |
| 886 | // Skip any register results. |
| 887 | .skip(results.regs().len()) |
| 888 | .enumerate() |
| 889 | { |
| 890 | let value_index = context.stack.len() - i - 1; |
| 891 | let val = context.stack.inner()[value_index]; |
| 892 | match (val, operand) { |
| 893 | (Val::Memory(mem), ABIOperand::Stack { offset, size, .. }) => { |
nothing calls this directly
no test coverage detected