Performs the tail end of [`Vm::call`] by returning the values as determined by `rets` according to Pulley's ABI. The `old_ret` value should have been provided from `call_start` previously. # Unsafety In addition to the invariants documented for `call`, this may only be called after `call_run`.
(
&'a mut self,
old_ret: *mut u8,
rets: impl IntoIterator<Item = RegType> + 'a,
)
| 162 | /// In addition to the invariants documented for `call`, this may |
| 163 | /// only be called after `call_run`. |
| 164 | pub unsafe fn call_end<'a>( |
| 165 | &'a mut self, |
| 166 | old_ret: *mut u8, |
| 167 | rets: impl IntoIterator<Item = RegType> + 'a, |
| 168 | ) -> impl Iterator<Item = Val> + 'a { |
| 169 | self.state.lr = old_ret; |
| 170 | // NB: make sure this method stays in sync with |
| 171 | // `PulleyMachineDeps::compute_arg_locs`! |
| 172 | |
| 173 | let mut x_rets = (0..15).map(|x| unsafe { XReg::new_unchecked(x) }); |
| 174 | let mut f_rets = (0..16).map(|f| unsafe { FReg::new_unchecked(f) }); |
| 175 | #[cfg(not(pulley_disable_interp_simd))] |
| 176 | let mut v_rets = (0..16).map(|v| unsafe { VReg::new_unchecked(v) }); |
| 177 | |
| 178 | rets.into_iter().map(move |ty| match ty { |
| 179 | RegType::XReg => match x_rets.next() { |
| 180 | Some(reg) => Val::XReg(self.state[reg]), |
| 181 | None => todo!("stack slots"), |
| 182 | }, |
| 183 | RegType::FReg => match f_rets.next() { |
| 184 | Some(reg) => Val::FReg(self.state[reg]), |
| 185 | None => todo!("stack slots"), |
| 186 | }, |
| 187 | #[cfg(not(pulley_disable_interp_simd))] |
| 188 | RegType::VReg => match v_rets.next() { |
| 189 | Some(reg) => Val::VReg(self.state[reg]), |
| 190 | None => todo!("stack slots"), |
| 191 | }, |
| 192 | #[cfg(pulley_disable_interp_simd)] |
| 193 | RegType::VReg => panic!("simd support disabled at compile time"), |
| 194 | }) |
| 195 | } |
| 196 | |
| 197 | /// Returns the current `fp` register value. |
| 198 | pub fn fp(&self) -> *mut u8 { |