dev/pbs #8

Merged
bquarkz merged 74 commits from dev/pbs into master 2026-02-03 15:28:31 +00:00
5 changed files with 61 additions and 34 deletions
Showing only changes of commit 239d7251c3 - Show all commits

View File

@ -1,6 +1,5 @@
use crate::virtual_machine::{ProgramImage, Value};
use prometeu_bytecode::v0::{BytecodeModule, DebugInfo, ConstantPoolEntry};
use prometeu_bytecode::opcode::OpCode;
use crate::v0::{BytecodeModule, DebugInfo, ConstantPoolEntry, FunctionMeta};
use crate::opcode::OpCode;
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Eq)]
@ -11,8 +10,18 @@ pub enum LinkError {
pub struct Linker;
/// Internal representation for linking process
#[derive(Debug)]
pub struct LinkedProgram {
pub rom: Vec<u8>,
pub constant_pool: Vec<ConstantPoolEntry>,
pub functions: Vec<FunctionMeta>,
pub debug_info: Option<DebugInfo>,
pub exports: HashMap<String, u32>,
}
impl Linker {
pub fn link(modules: &[BytecodeModule]) -> Result<ProgramImage, LinkError> {
pub fn link(modules: &[BytecodeModule]) -> Result<LinkedProgram, LinkError> {
let mut combined_code = Vec::new();
let mut combined_functions = Vec::new();
let mut combined_constants = Vec::new();
@ -56,14 +65,7 @@ impl Linker {
// Relocate constant pool entries for this module
for entry in &module.const_pool {
combined_constants.push(match entry {
ConstantPoolEntry::Int32(v) => Value::Int32(*v),
ConstantPoolEntry::Int64(v) => Value::Int64(*v),
ConstantPoolEntry::Float64(v) => Value::Float(*v),
ConstantPoolEntry::Boolean(v) => Value::Boolean(*v),
ConstantPoolEntry::String(v) => Value::String(v.clone()),
ConstantPoolEntry::Null => Value::Null,
});
combined_constants.push(entry.clone());
}
// Patch relocations for imports
@ -143,21 +145,21 @@ impl Linker {
None
};
Ok(ProgramImage::new(
combined_code,
combined_constants,
combined_functions,
Ok(LinkedProgram {
rom: combined_code,
constant_pool: combined_constants,
functions: combined_functions,
debug_info,
exports,
))
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use prometeu_bytecode::v0::{BytecodeModule, FunctionMeta, Export, Import};
use prometeu_bytecode::opcode::OpCode;
use crate::v0::{BytecodeModule, FunctionMeta, Export, Import};
use crate::opcode::OpCode;
#[test]
fn test_linker_basic() {
@ -280,8 +282,8 @@ mod tests {
let result = Linker::link(&[m1, m2]).unwrap();
assert_eq!(result.constant_pool.len(), 2);
assert_eq!(result.constant_pool[0], Value::Int32(42));
assert_eq!(result.constant_pool[1], Value::Int32(99));
assert_eq!(result.constant_pool[0], ConstantPoolEntry::Int32(42));
assert_eq!(result.constant_pool[1], ConstantPoolEntry::Int32(99));
// Code for module 1 (starts at 0)
let idx1 = u32::from_le_bytes(result.rom[2..6].try_into().unwrap());

View File

@ -1,3 +1,5 @@
pub mod linker;
use crate::opcode::OpCode;
use crate::abi::SourceSpan;

View File

@ -7,7 +7,6 @@ pub mod local_addressing;
pub mod opcode_spec;
pub mod bytecode;
pub mod verifier;
pub mod linker;
use crate::hardware::HardwareBridge;
pub use program::ProgramImage;
@ -16,7 +15,6 @@ pub use value::Value;
pub use virtual_machine::{BudgetReport, LogicalFrameEndingReason, VirtualMachine};
pub use prometeu_bytecode::abi::TrapInfo;
pub use verifier::VerifierError;
pub use linker::{Linker, LinkError};
pub type SyscallId = u32;
@ -31,7 +29,6 @@ pub enum VmInitError {
InvalidFormat,
UnsupportedFormat,
PbsV0LoadFailed(prometeu_bytecode::v0::LoadError),
LinkFailed(LinkError),
EntrypointNotFound,
VerificationFailed(VerifierError),
}

View File

@ -1,5 +1,5 @@
use crate::virtual_machine::Value;
use prometeu_bytecode::v0::{FunctionMeta, DebugInfo};
use prometeu_bytecode::v0::{FunctionMeta, DebugInfo, BytecodeModule, ConstantPoolEntry};
use prometeu_bytecode::abi::TrapInfo;
use std::sync::Arc;
use std::collections::HashMap;
@ -63,3 +63,31 @@ impl ProgramImage {
.map(|(_, name)| name.as_str())
}
}
impl From<BytecodeModule> for ProgramImage {
fn from(module: BytecodeModule) -> Self {
let constant_pool: Vec<Value> = module.const_pool.iter().map(|entry| {
match entry {
ConstantPoolEntry::Null => Value::Null,
ConstantPoolEntry::Int64(v) => Value::Int64(*v),
ConstantPoolEntry::Float64(v) => Value::Float(*v),
ConstantPoolEntry::Boolean(v) => Value::Boolean(*v),
ConstantPoolEntry::String(v) => Value::String(v.clone()),
ConstantPoolEntry::Int32(v) => Value::Int32(*v),
}
}).collect();
let mut exports = HashMap::new();
for export in module.exports {
exports.insert(export.symbol, export.func_idx);
}
ProgramImage::new(
module.code,
constant_pool,
module.functions,
module.debug_info,
exports,
)
}
}

View File

@ -125,21 +125,19 @@ impl VirtualMachine {
let program = if program_bytes.starts_with(b"PBS\0") {
match prometeu_bytecode::v0::BytecodeLoader::load(&program_bytes) {
Ok(module) => {
// Link module(s)
let mut linked_program = crate::virtual_machine::Linker::link(&[module])
.map_err(VmInitError::LinkFailed)?;
// Run verifier on the linked program
let max_stacks = crate::virtual_machine::verifier::Verifier::verify(&linked_program.rom, &linked_program.functions)
// Run verifier on the module
let max_stacks = crate::virtual_machine::verifier::Verifier::verify(&module.code, &module.functions)
.map_err(VmInitError::VerificationFailed)?;
let mut functions = linked_program.functions.as_ref().to_vec();
let mut program = ProgramImage::from(module);
let mut functions = program.functions.as_ref().to_vec();
for (func, max_stack) in functions.iter_mut().zip(max_stacks) {
func.max_stack_slots = max_stack;
}
linked_program.functions = std::sync::Arc::from(functions);
program.functions = std::sync::Arc::from(functions);
linked_program
program
}
Err(prometeu_bytecode::v0::LoadError::InvalidVersion) => return Err(VmInitError::UnsupportedFormat),
Err(e) => {