2026-03-24 13:40:31 +00:00

56 lines
2.4 KiB
Rust

//! Shared bytecode layout utilities, used by both compiler (emitter/linker)
//! and the VM (verifier/loader). This ensures a single source of truth for
//! how function ranges and jump targets are interpreted post-link.
use crate::FunctionMeta;
/// Returns the absolute end (exclusive) of the function at `func_idx`,
/// defined as the minimum `code_offset` of any subsequent function, or
/// `code_len_total` if this is the last function.
#[inline]
pub fn function_end_from_next(functions: &[FunctionMeta], func_idx: usize, code_len_total: usize) -> usize {
let start = functions.get(func_idx).map(|f| f.code_offset as usize).unwrap_or(0);
let mut end = code_len_total;
for (j, other) in functions.iter().enumerate() {
if j == func_idx { continue; }
let other_start = other.code_offset as usize;
if other_start > start && other_start < end {
end = other_start;
}
}
end
}
/// Returns the length (in bytes) of the function at `func_idx`, using
/// the canonical definition: end = start of next function (exclusive),
/// or total code len if last.
#[inline]
pub fn function_len_from_next(functions: &[FunctionMeta], func_idx: usize, code_len_total: usize) -> usize {
let start = functions.get(func_idx).map(|f| f.code_offset as usize).unwrap_or(0);
let end = function_end_from_next(functions, func_idx, code_len_total);
end.saturating_sub(start)
}
/// Recomputes all `code_len` values in place from the next function start
/// (exclusive end), using the combined code buffer length for the last one.
pub fn recompute_function_lengths_in_place(functions: &mut [FunctionMeta], code_len_total: usize) {
for i in 0..functions.len() {
let start = functions[i].code_offset as usize;
let end = function_end_from_next(functions, i, code_len_total);
functions[i].code_len = end.saturating_sub(start) as u32;
}
}
/// Finds the function index that contains `pc_abs` (absolute), using the
/// canonical ranges (end = next start, exclusive). Returns `None` if none.
pub fn function_index_by_pc(functions: &[FunctionMeta], code_len_total: usize, pc_abs: usize) -> Option<usize> {
for i in 0..functions.len() {
let start = functions[i].code_offset as usize;
let end = function_end_from_next(functions, i, code_len_total);
if pc_abs >= start && pc_abs < end {
return Some(i);
}
}
None
}