From 4625a68def8b5110e6ab04d40908503164ea26fd Mon Sep 17 00:00:00 2001 From: Patrick Mill Date: Thu, 29 Oct 2026 12:33:23 -0400 Subject: [PATCH] recomp-abi: Library::interpret and interpret_at, for a host to have the interpreter run chosen functions interpret marks the function starting at an address stale, as if its code had changed, so the interpreter runs it. interpret_at marks every function whose code takes in an address: code can be part of more than one function, so a host that has to stop at an address marks each of them, not only the one starting there. --- abi/src/lib.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/abi/src/lib.rs b/abi/src/lib.rs index 93dd167..3abd3c2 100644 --- a/abi/src/lib.rs +++ b/abi/src/lib.rs @@ -444,6 +444,46 @@ impl Library { stale } + /// marks the function of unit that starts at start stale, as if its code + /// had changed, so that the interpreter runs it, for a host that has to + /// see it run instruction by instruction. whether there is one. + pub fn interpret(&mut self, unit: usize, start: u32) -> bool { + let Some(origins) = self.origins(unit) else { return false }; + let Some(index) = origins.functions().iter().position(|function| function.start == start) else { return false }; + // SAFETY: as in check, a flag and a start per function + unsafe { + *origins.stale.add(index) = 1; + *origins.starts.add(index) = NO_START; + } + true + } + + /// marks every function of unit whose code takes in address stale, so + /// that the interpreter runs whatever reaches it, for a host that has to + /// stop there: code can be part of more than one function, and each one + /// would run it. how many there are. + pub fn interpret_at(&mut self, unit: usize, address: u32) -> usize { + let Some(origins) = self.origins(unit) else { return 0 }; + let pieces = origins.pieces(); + let runs = origins.runs(); + let mut marked = 0; + for (index, function) in origins.functions().iter().enumerate() { + let runs = &runs[function.first as usize..(function.first + function.count) as usize]; + let takes_in = runs.iter().any(|run| { + pieces[run.first as usize..run.end as usize].iter().any(|piece| (piece.start..piece.end).contains(&address)) + }); + if takes_in { + // SAFETY: as in check, a flag and a start per function + unsafe { + *origins.stale.add(index) = 1; + *origins.starts.add(index) = NO_START; + } + marked += 1; + } + } + marked + } + /// the module called name. pub fn module_index(&self, name: &str) -> Option { self.modules().iter().position(|module| module.name() == name)