Add basic, but failing, implementation of load/store object.

This commit is contained in:
Jesse Brault 2024-12-28 08:52:35 -06:00
parent 574f7ea7a1
commit 652c1dd7f2
2 changed files with 136 additions and 0 deletions

View File

@ -213,6 +213,16 @@ macro_rules! next_64_le {
}; };
} }
macro_rules! next_usize_le {
( $byte_code: expr ) => {{
let mut u: usize = 0;
for i in 0..std::mem::size_of::<usize>() {
u += next_8!($byte_code, usize) << (8 * i);
}
u
}};
}
macro_rules! read_array_u8 { macro_rules! read_array_u8 {
( $iter: expr ) => {{ ( $iter: expr ) => {{
let arr_length = next_8!($iter, u8); let arr_length = next_8!($iter, u8);
@ -284,6 +294,70 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
let source_value = state.registers.get(source_register).unwrap(); let source_value = state.registers.get(source_register).unwrap();
state.registers[target_register] = source_value.clone(); state.registers[target_register] = source_value.clone();
} }
LOAD_OBJECT => {
let target_register = next_8!(iter, usize);
let source_register = next_8!(iter, usize);
let offset = next_usize_le!(iter);
let source_object = state.registers
.get(source_register)
.unwrap()
.expect_object();
let object = unsafe {
Rc::from_raw(source_object.data.add(offset).cast::<DmAllocObject>())
};
state.registers[target_register] = DvmValue::Object(object);
}
STORE => {
let target_register = next_8!(iter, usize);
let offset = next_usize_le!(iter);
let source_register = next_8!(iter, usize);
let target_alloc_object = state
.registers
.get(target_register)
.unwrap()
.expect_object();
let source_value = std::mem::replace(&mut state.registers[source_register], DvmValue::Uninit);
match source_value {
DvmValue::Int(i) => {
write_bytes!(target_alloc_object.data, offset, i.to_ne_bytes());
}
DvmValue::Byte(b) => unsafe {
target_alloc_object.data.add(offset).write(b);
},
DvmValue::Long(l) => {
write_bytes!(target_alloc_object.data, offset, l.to_ne_bytes());
}
DvmValue::Double(d) => {
write_bytes!(target_alloc_object.data, offset, d.to_ne_bytes());
}
DvmValue::Boolean(b) => unsafe {
target_alloc_object.data.add(offset).write(b as u8);
},
DvmValue::Object(source_object) => {
let source_object_ptr = Rc::into_raw(source_object);
write_bytes!(
target_alloc_object.data,
offset,
(source_object_ptr as usize).to_ne_bytes()
);
}
DvmValue::USize(u) => {
write_bytes!(target_alloc_object.data, offset, u.to_ne_bytes());
}
DvmValue::Uninit => {
panic!("Cannot store DvmValue::Uninit to object.")
}
DvmValue::Void => {
panic!("Cannot store DvmValue::Void to object.")
}
}
}
ALLOC => { ALLOC => {
let target_register = next_8!(iter, usize); let target_register = next_8!(iter, usize);
let alloc_size = next_32_le!(iter, usize); let alloc_size = next_32_le!(iter, usize);
@ -516,6 +590,8 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
#[cfg(test)] #[cfg(test)]
mod run_code_tests { mod run_code_tests {
use crate::vm::dm_type::DmType;
use crate::vm::object_type::{DmField, DmImplementation};
use super::*; use super::*;
macro_rules! assert_register { macro_rules! assert_register {
@ -531,6 +607,13 @@ mod run_code_tests {
(DvmState::new(), DvmContext::new()) (DvmState::new(), DvmContext::new())
} }
fn impl_with_object_field() -> DmImplementation {
let mut dm_impl = DmImplementation::new("ImplWithObjectField", "ImplWithObjectField", None);
let object_field = DmField::new("object_field", DmType::Object, 0);
dm_impl.fields.push(object_field);
dm_impl
}
#[test] #[test]
fn mov_1_as_int() { fn mov_1_as_int() {
let mut code = Vec::new(); let mut code = Vec::new();
@ -568,4 +651,29 @@ mod run_code_tests {
run_byte_code(&mut state, &context, &code); run_byte_code(&mut state, &context, &code);
assert_register!(DvmValue::Int(1), state, 0); assert_register!(DvmValue::Int(1), state, 0);
} }
#[test]
fn load_object() {
let dummy_impl = impl_with_object_field();
let dummy_impl_rc = Rc::new(dummy_impl);
let dummy_impl_object_field = dummy_impl_rc.fields.iter().find(|field| {
field.name() == "object_field"
}).unwrap();
let mut dummy_lib = DmLib::new("dummy");
dummy_lib.implementations.push(dummy_impl_rc.clone());
let mut code = Vec::new();
add_alloc(&mut code, 0, dummy_impl_rc.size_in_bytes() as u32, &dummy_impl_rc.fqn);
add_alloc(&mut code, 1, dummy_impl_rc.size_in_bytes() as u32, &dummy_impl_rc.fqn);
add_store(&mut code, 0, dummy_impl_object_field.data_offset(), 1);
add_load_object(&mut code, 2, 0, dummy_impl_object_field.data_offset());
let (mut state, mut context) = setup();
state.registers.resize(3, DvmValue::Uninit);
context.load_libs(vec![Rc::new(dummy_lib)]);
run_byte_code(&mut state, &context, &code);
let referenced_object = state.registers.get(1).unwrap().expect_object();
assert_register!(DvmValue::Object(referenced_object), state, 2);
}
} }

View File

@ -51,6 +51,10 @@ pub const MOV_SIZE_OF: u8 = 0x30;
pub const MULTIPLY: u8 = 0x40; pub const MULTIPLY: u8 = 0x40;
pub const LOAD_OBJECT: u8 = 0x50;
pub const STORE: u8 = 0x60;
macro_rules! push_number { macro_rules! push_number {
( $dest: expr, $num: expr ) => { ( $dest: expr, $num: expr ) => {
push_bytes!($dest, $num.to_le_bytes()) push_bytes!($dest, $num.to_le_bytes())
@ -113,6 +117,30 @@ pub fn add_mov_register_to(
code.push(source_register); code.push(source_register);
} }
pub fn add_load_object(
code: &mut Vec<u8>,
target_register: u8,
source_register: u8,
offset: usize
) {
code.push(LOAD_OBJECT);
code.push(target_register);
code.push(source_register);
push_number!(code, offset);
}
pub fn add_store(
code: &mut Vec<u8>,
target_register: u8,
offset: usize,
source_register: u8,
) {
code.push(STORE);
code.push(target_register);
push_number!(code, offset);
code.push(source_register);
}
pub fn add_mov_const( pub fn add_mov_const(
code: &mut Vec<u8>, code: &mut Vec<u8>,
address_register: u8, address_register: u8,