63 lines
2.0 KiB
Rust
63 lines
2.0 KiB
Rust
use crate::virtual_machine::Value;
|
|
use prometeu_bytecode::v0::{FunctionMeta, DebugInfo};
|
|
use prometeu_bytecode::abi::TrapInfo;
|
|
use std::sync::Arc;
|
|
|
|
#[derive(Debug, Clone, Default)]
|
|
pub struct ProgramImage {
|
|
pub rom: Arc<[u8]>,
|
|
pub constant_pool: Arc<[Value]>,
|
|
pub functions: Arc<[FunctionMeta]>,
|
|
pub debug_info: Option<DebugInfo>,
|
|
}
|
|
|
|
impl ProgramImage {
|
|
pub fn new(rom: Vec<u8>, constant_pool: Vec<Value>, mut functions: Vec<FunctionMeta>, debug_info: Option<DebugInfo>) -> Self {
|
|
if functions.is_empty() && !rom.is_empty() {
|
|
functions.push(FunctionMeta {
|
|
code_offset: 0,
|
|
code_len: rom.len() as u32,
|
|
..Default::default()
|
|
});
|
|
}
|
|
Self {
|
|
rom: Arc::from(rom),
|
|
constant_pool: Arc::from(constant_pool),
|
|
functions: Arc::from(functions),
|
|
debug_info,
|
|
}
|
|
}
|
|
|
|
pub fn create_trap(&self, code: u32, opcode: u16, mut message: String, pc: u32) -> TrapInfo {
|
|
let span = self.debug_info.as_ref().and_then(|di| {
|
|
di.pc_to_span.iter().find(|(p, _)| *p == pc).map(|(_, s)| s.clone())
|
|
});
|
|
|
|
if let Some(func_idx) = self.find_function_index(pc) {
|
|
if let Some(func_name) = self.get_function_name(func_idx) {
|
|
message = format!("{} (in function {})", message, func_name);
|
|
}
|
|
}
|
|
|
|
TrapInfo {
|
|
code,
|
|
opcode,
|
|
message,
|
|
pc,
|
|
span,
|
|
}
|
|
}
|
|
|
|
pub fn find_function_index(&self, pc: u32) -> Option<usize> {
|
|
self.functions.iter().position(|f| {
|
|
pc >= f.code_offset && pc < (f.code_offset + f.code_len)
|
|
})
|
|
}
|
|
|
|
pub fn get_function_name(&self, func_idx: usize) -> Option<&str> {
|
|
self.debug_info.as_ref()
|
|
.and_then(|di| di.function_names.iter().find(|(idx, _)| *idx as usize == func_idx))
|
|
.map(|(_, name)| name.as_str())
|
|
}
|
|
}
|