Implement basic alloc and dealloc functionality.
This commit is contained in:
parent
e8019366ee
commit
e4ee8fd2db
@ -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();
|
||||||
|
@ -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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user