Implement basic alloc and dealloc functionality.

This commit is contained in:
Jesse Brault 2024-11-28 08:01:50 -06:00
parent e8019366ee
commit e4ee8fd2db
3 changed files with 79 additions and 27 deletions

View File

@ -141,6 +141,7 @@ mod tests {
} }
#[test] #[test]
#[cfg_attr(miri, ignore)]
fn simple_ns_file() { fn simple_ns_file() {
let mut src_file = File::open(Path::new("test-data/lexer/simple_ns.dm")).unwrap(); let mut src_file = File::open(Path::new("test-data/lexer/simple_ns.dm")).unwrap();
let mut src = String::new(); let mut src = String::new();

View File

@ -1,7 +1,13 @@
mod op_codes; mod op_codes;
use op_codes::*; use op_codes::*;
use std::alloc::{alloc_zeroed, Layout}; use std::alloc::{alloc_zeroed, dealloc, Layout};
struct DmObject {
pointer: *mut u8,
size: usize,
layout: Layout,
}
pub fn run(code: &Vec<u8>, registers: &mut Vec<u64>, register_types: &mut Vec<RegisterType>) { pub fn run(code: &Vec<u8>, registers: &mut Vec<u64>, register_types: &mut Vec<RegisterType>) {
let mut i = 0; let mut i = 0;
@ -41,29 +47,50 @@ pub fn run(code: &Vec<u8>, registers: &mut Vec<u64>, register_types: &mut Vec<Re
} }
ALLOC => { ALLOC => {
let target_register = code[i + 1] as usize; let target_register = code[i + 1] as usize;
let n_bytes_to_allocate = code[i + 2] as u32 let size = code[i + 2] as usize
+ ((code[i + 3] as u32) << 8) + ((code[i + 3] as usize) << 8)
+ ((code[i + 4] as u32) << 16) + ((code[i + 4] as usize) << 16)
+ ((code[i + 5] as u32) << 24); + ((code[i + 5] as usize) << 24);
let layout = Layout::from_size_align(n_bytes_to_allocate as usize, 4).unwrap(); let layout = Layout::from_size_align(size, 4).unwrap();
let allocated = unsafe { alloc_zeroed(layout) }; let pointer = unsafe { alloc_zeroed(layout) };
registers[target_register] = allocated as u64; let dm_object = Box::new(DmObject {
pointer,
size,
layout,
});
let dm_object_pointer = Box::into_raw(dm_object) as u64;
registers[target_register] = dm_object_pointer;
register_types[target_register] = RegisterType::Pointer; register_types[target_register] = RegisterType::Pointer;
i += 6; i += 6;
} }
DEALLOC => {
let target_register = code[i + 1] as usize;
let box_address = registers[target_register];
unsafe {
let dm_object = Box::from_raw(box_address as *mut DmObject);
dealloc(dm_object.pointer, dm_object.layout);
}
registers[target_register] = 0;
register_types[target_register] = RegisterType::Int;
i += 2;
}
MOV_INT_TO => { MOV_INT_TO => {
let target_register = code[i + 1] as usize; let target_register = code[i + 1] as usize;
if register_types[target_register] != RegisterType::Pointer { if register_types[target_register] != RegisterType::Pointer {
panic!("target_register {} is not a Pointer", target_register); panic!("target_register {} is not a Pointer", target_register);
} }
let offset = convert_to_u32(&code[(i + 2)..(i + 6)]) as isize; let offset = convert_to_u32(&code[(i + 2)..(i + 6)]) as isize;
let target = registers[target_register] as *mut u8; let box_address = registers[target_register];
unsafe { let new_address = unsafe {
target.offset(offset).write(code[i + 6]); let dm_object = Box::from_raw(box_address as *mut DmObject);
target.offset(offset + 1).write(code[i + 7]); let pointer = dm_object.pointer;
target.offset(offset + 2).write(code[i + 8]); pointer.offset(offset).write(code[i + 6]);
target.offset(offset + 3).write(code[i + 9]); pointer.offset(offset + 1).write(code[i + 7]);
} pointer.offset(offset + 2).write(code[i + 8]);
pointer.offset(offset + 3).write(code[i + 9]);
Box::into_raw(dm_object) as u64
};
registers[target_register] = new_address;
i += 10; i += 10;
} }
_ => panic!("Invalid code instruction"), _ => panic!("Invalid code instruction"),
@ -78,6 +105,7 @@ fn convert_to_u32(bytes: &[u8]) -> u32 {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use std::alloc::dealloc;
fn init_registers(n_registers: usize) -> (Vec<u64>, Vec<RegisterType>) { fn init_registers(n_registers: usize) -> (Vec<u64>, Vec<RegisterType>) {
(vec![0; n_registers], vec![RegisterType::Int; n_registers]) (vec![0; n_registers], vec![RegisterType::Int; n_registers])
@ -128,9 +156,22 @@ mod tests {
let mut registers = vec![0; 16]; let mut registers = vec![0; 16];
let mut register_types = vec![RegisterType::Int; 16]; let mut register_types = vec![RegisterType::Int; 16];
run(&code, &mut registers, &mut register_types); run(&code, &mut registers, &mut register_types);
let target = registers[0] as *mut u8; let box_address = registers[0];
unsafe { unsafe {
assert_eq!(0xff, *target); let dm_object = Box::from_raw(box_address as *mut DmObject);
assert_eq!(0xff, *dm_object.pointer);
dealloc(dm_object.pointer, dm_object.layout);
} }
} }
#[test]
fn alloc_and_dealloc_expect_register_cleared() {
let mut code = Vec::new();
add_alloc(&mut code, 0, 4);
add_dealloc(&mut code, 0);
let (mut registers, mut register_types) = init_registers(1);
run(&code, &mut registers, &mut register_types);
assert_eq!(0, registers[0]);
assert_eq!(RegisterType::Int, register_types[0]);
}
} }

View File

@ -2,35 +2,40 @@
/// - 0: opcode /// - 0: opcode
/// - 1: register /// - 1: register
/// - 2..5: operand /// - 2..5: operand
pub const MOV_INT: u8 = 0x00; pub const MOV_INT: u8 = 0x01;
pub const MOV_LONG: u8 = 0x01; pub const MOV_LONG: u8 = 0x02;
pub const MOV_DOUBLE: u8 = 0x02; pub const MOV_DOUBLE: u8 = 0x03;
/// ## mov(target_register: u8, source_register: u8) /// ## mov(target_register: u8, source_register: u8)
/// 0: opcode /// 0: opcode
/// 1: target_register /// 1: target_register
/// 2: source_register /// 2: source_register
pub const MOV_REGISTER: u8 = 0x03; pub const MOV_REGISTER: u8 = 0x04;
/// ## alloc(register: u8, size: u32) /// ## alloc(register: u8, size: u32)
/// 0: opcode /// 0: opcode
/// 1: register /// 1: register
/// 2..5: size /// 2..5: size
pub const ALLOC: u8 = 0x04; pub const ALLOC: u8 = 0x05;
/// ## dealloc(register: u8)
/// 0: opcode
/// 1: register
pub const DEALLOC: u8 = 0x06;
/// ## mov_int_to(register: u8, offset: u32, operand: u32) /// ## mov_int_to(register: u8, offset: u32, operand: u32)
/// 0: opcode /// 0: opcode
/// 1: register /// 1: register
/// 2..5: offset /// 2..5: offset
/// 6..9: operand /// 6..9: operand
pub const MOV_INT_TO: u8 = 0x05; pub const MOV_INT_TO: u8 = 0x07;
pub const MOV_LONG_TO: u8 = 0x06; pub const MOV_LONG_TO: u8 = 0x08;
pub const MOV_DOUBLE_TO: u8 = 0x07; pub const MOV_DOUBLE_TO: u8 = 0x09;
pub const MOV_REGISTER_TO: u8 = 0x08; pub const MOV_REGISTER_TO: u8 = 0x0a;
#[derive(PartialEq, Eq, Clone)] #[derive(PartialEq, Eq, Clone, Debug)]
pub enum RegisterType { pub enum RegisterType {
Int, Int,
Long, Long,
@ -60,6 +65,11 @@ pub fn add_alloc(code: &mut Vec<u8>, register: u8, size: u32) {
} }
} }
pub fn add_dealloc(code: &mut Vec<u8>, register: u8) {
code.push(DEALLOC);
code.push(register);
}
pub fn add_mov_int_to(code: &mut Vec<u8>, register: u8, offset: u32, operand: u32) { pub fn add_mov_int_to(code: &mut Vec<u8>, register: u8, offset: u32, operand: u32) {
code.push(MOV_INT_TO); code.push(MOV_INT_TO);
code.push(register); code.push(register);