56 lines
2.4 KiB
Rust
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
|
|
}
|