From d5153cc9fb88c87b1a7e05ac91332bf23d1c051c Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Fri, 13 Dec 2024 20:18:02 -0600 Subject: [PATCH] Various work on running byte code. --- dm_lib/std/core/array.dm | 6 +- dm_lib/std/core/string.dm | 5 +- dm_lib/std/unsafe/mem.dm | 16 +- src/vm/dvm_value.rs | 20 +- src/vm/lib/mod.rs | 1 + src/vm/mem.rs | 29 +- src/vm/mod.rs | 465 +++++++++++++++++++++++++++++--- src/vm/object_type.rs | 10 +- src/vm/op_codes.rs | 16 -- src/vm/platform/std_lib/core.rs | 37 ++- 10 files changed, 524 insertions(+), 81 deletions(-) diff --git a/dm_lib/std/core/array.dm b/dm_lib/std/core/array.dm index c2d7eef..260b51f 100644 --- a/dm_lib/std/core/array.dm +++ b/dm_lib/std/core/array.dm @@ -12,7 +12,7 @@ pub int Array : Monad + Default + Empty { impl ArrayImpl : Array { - fld pointer: Pointer + fld pointer: Pointer fld length: Int pub unsafe ctor(length: Int) { @@ -20,12 +20,12 @@ impl ArrayImpl : Array { self.length = length } - pub ctor(pointer: Pointer, length: Int) { + pub ctor(pointer: Pointer, length: Int) { self.pointer = pointer self.length = length } - pub unsafe fn set(index: Int, item: Pointer) { + pub unsafe fn set(index: Int, item: Pointer) { pointer.offset(index * T::size()).write(item.read()) } diff --git a/dm_lib/std/core/string.dm b/dm_lib/std/core/string.dm index 317c26f..3d2974a 100644 --- a/dm_lib/std/core/string.dm +++ b/dm_lib/std/core/string.dm @@ -13,8 +13,7 @@ pub int String : Display { } -impl Utf8String(bytes: Array) : String { - encoding = Encoding::Utf8 +impl StringImpl(bytes: Array, /* encoding: Encoding */) { length = bytes.length characters = lazy { todo('parse the utf8 bytes and return an Array') @@ -27,6 +26,6 @@ pub mod string { // let bytes = array::of(0x64, 0x65, 0x69, 0x6d, 0x6f, 0x73) // let s = string::from_utf8_bytes(bytes) // println s // "deimos" - fn from_utf8_bytes(bytes: Array): String = Utf8String(bytes) + fn from_utf8_bytes(bytes: Array): String = StringImpl(bytes, /* Encoding::Utf8 */) } diff --git a/dm_lib/std/unsafe/mem.dm b/dm_lib/std/unsafe/mem.dm index 4e33109..60651ec 100644 --- a/dm_lib/std/unsafe/mem.dm +++ b/dm_lib/std/unsafe/mem.dm @@ -1,18 +1,14 @@ ns std::unsafe -pub int Pointer {} +pub int Pointer -impl PointerImpl { - - fld raw_address: Long - fld size: Long - - decl ctor(size: Long) - -} +// Contains two fields: +// fld raw_address: Long +// fld size: Long +decl impl PointerImpl(size: Long) : Pointer pub mod mem { - pub fn alloc(size: Long): Pointer = PointerImpl(size) + pub fn alloc(size: Long): Pointer = PointerImpl(size) } diff --git a/src/vm/dvm_value.rs b/src/vm/dvm_value.rs index 524049b..7c4730b 100644 --- a/src/vm/dvm_value.rs +++ b/src/vm/dvm_value.rs @@ -9,5 +9,23 @@ pub enum DvmValue { Double(f64), Boolean(bool), Pointer(Rc), - Unit, + Uninit, +} + +impl DvmValue { + pub fn expect_long(&self) -> i64 { + if let DvmValue::Long(l) = self { + *l + } else { + panic!("Expected DvmValue::long, but found {:?}", self) + } + } + + pub fn expect_pointer(&self) -> Rc { + if let DvmValue::Pointer(p) = self { + p.clone() + } else { + panic!("Expected DvmValue::Pointer, but found {:?}", self); + } + } } diff --git a/src/vm/lib/mod.rs b/src/vm/lib/mod.rs index 2bd771d..d428735 100644 --- a/src/vm/lib/mod.rs +++ b/src/vm/lib/mod.rs @@ -26,6 +26,7 @@ impl DmLib { } } +#[derive(Debug)] pub enum DmConstant { String(String), } diff --git a/src/vm/mem.rs b/src/vm/mem.rs index 418962c..ecd7e7a 100644 --- a/src/vm/mem.rs +++ b/src/vm/mem.rs @@ -1,17 +1,40 @@ use crate::vm::dm_type::DmType; use crate::vm::dvm_value::DvmValue; use crate::vm::object_type::{DmField, DmImplementation}; -use std::alloc::Layout; +use std::alloc::{alloc, dealloc, Layout}; +use std::collections::HashSet; use std::rc::Rc; #[derive(Debug, PartialEq, Eq)] pub struct DmAllocObject { pub data: *mut u8, + pub units: HashSet, pub size: usize, pub layout: Layout, pub implementation: Rc, } +impl DmAllocObject { + pub fn new(size: usize, implementation: Rc) -> Self { + let layout = Layout::from_size_align(size, 1).unwrap(); + DmAllocObject { + data: unsafe { alloc(layout) }, + units: HashSet::new(), + size, + layout, + implementation, + } + } +} + +impl Drop for DmAllocObject { + fn drop(&mut self) { + unsafe { + dealloc(self.data, self.layout); + } + } +} + pub unsafe fn get_field_value(dm_field: &DmField, self_object: &DmAllocObject) -> DvmValue { let data_size = dm_field.dm_type().size_in_bytes(); let mut raw_data: Vec = Vec::with_capacity(data_size); @@ -29,13 +52,13 @@ pub unsafe fn get_field_value(dm_field: &DmField, self_object: &DmAllocObject) - DmType::Double => DvmValue::Double(f64::from_ne_bytes( raw_data[0..data_size].try_into().unwrap(), )), - DmType::Boolean => DvmValue::Boolean(raw_data[0] == 1), + DmType::Boolean => DvmValue::Boolean(raw_data[0] != 0), DmType::Pointer => { // read the pointer's (address) value let address = usize::from_ne_bytes(raw_data[0..data_size].try_into().unwrap()); DvmValue::Pointer(Rc::from_raw(address as *const DmAllocObject)) } - DmType::Unit => DvmValue::Unit, + DmType::Unit => DvmValue::Uninit, } } diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 3b20c4e..d156ab6 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -13,7 +13,7 @@ use crate::vm::mem::{get_field_value, DmAllocObject}; use crate::vm::object_type::DmFn; use crate::vm::platform::init_platform_functions; use op_codes::*; -use std::alloc::{alloc, Layout}; +use std::alloc::{alloc, dealloc, Layout}; use std::collections::HashMap; use std::rc::Rc; use util::{get_32_le, get_64_le}; @@ -21,19 +21,15 @@ use util::{get_32_le, get_64_le}; pub type PlatformFunction = fn(args: Vec, &mut DmVirtualMachine) -> DvmValue; enum CallFrame { - PlatformCall(PlatformCallFrame), - DeimosCall(DeimosCallFrame), + PlatformCall(CallFrameInfo), + DeimosCall(CallFrameInfo), } -pub struct PlatformCallFrame { - pub name: String, - pub args: Vec, -} - -struct DeimosCallFrame { - return_address: usize, +struct CallFrameInfo { + fn_fqn: String, } +#[deprecated] pub struct DmVirtualMachine { libs: Vec, functions: HashMap>, @@ -44,19 +40,59 @@ pub struct DmVirtualMachine { register_state_stack: Vec>, } +pub struct DvmContext { + libs: Vec, + functions: HashMap>, + platform_functions: HashMap>, +} + +impl DvmContext { + pub fn new() -> Self { + DvmContext { + libs: Vec::new(), + functions: HashMap::new(), + platform_functions: HashMap::new(), + } + } + + pub fn fn_by_fqn(&self, fqn: &str) -> Option> { + self.functions.get(fqn).cloned() + } + + pub fn platform_fn_by_fqn(&self, fqn: &str) -> Option> { + self.platform_functions.get(fqn).cloned() + } +} + +pub struct DvmState { + call_stack: Vec, + registers: Vec, + register_state_stack: Vec>, +} + +impl DvmState { + pub fn new() -> Self { + DvmState { + call_stack: Vec::new(), + registers: Vec::new(), + register_state_stack: Vec::new(), + } + } +} + fn load_functions(destination: &mut HashMap>, libs: &Vec) { - for module in libs { - for lib_fn in &module.functions { + for lib in libs { + for lib_fn in &lib.functions { destination.insert(lib_fn.fqn.clone(), lib_fn.clone()); } - for interface_function in module + for interface_function in lib .interfaces .iter() .flat_map(|interface| interface.get_functions()) { destination.insert(interface_function.fqn.clone(), interface_function.clone()); } - for implementation_function in module + for implementation_function in lib .implementations .iter() .flat_map(|implementation| &implementation.functions) @@ -69,6 +105,367 @@ fn load_functions(destination: &mut HashMap>, libs: &Vec } } +pub fn call_fn( + state: &mut DvmState, + context: &DvmContext, + dm_fn: &DmFn, + args: Vec, +) -> Option { + // save current state + state.call_stack.push(CallFrame::DeimosCall(CallFrameInfo { + fn_fqn: dm_fn.fqn.clone(), + })); + state.register_state_stack.push(state.registers.clone()); + + // zero registers and make sure there are enough for dm_function + state.registers.clear(); + if state.registers.len() < dm_fn.number_used_registers() { + state + .registers + .resize(dm_fn.number_used_registers(), DvmValue::Uninit); + } + + // push args + for arg in args { + state.registers.push(arg); + } + + // run the byte code + run_byte_code(state, context, &dm_fn.byte_code); + + // get return value + let return_value = state + .registers + .get(dm_fn.return_register() as usize) + .map(|m| m.clone()); + + // restore state + state.registers = state.register_state_stack.pop().unwrap(); + state.call_stack.pop(); + + // return result + return_value +} + +macro_rules! next_8 { + ( $byte_code: expr, $T: ident ) => { + $byte_code.next().unwrap() as $T + }; +} + +macro_rules! next_32_le { + ( $byte_code: expr, $T: ident ) => { + next_8!($byte_code, $T) + + (next_8!($byte_code, $T) << 8) + + (next_8!($byte_code, $T) << 16) + + (next_8!($byte_code, $T) << 24) + }; +} + +macro_rules! next_64_le { + ( $byte_code: expr, $T: ident ) => { + next_8!($byte_code, $T) + + (next_8!($byte_code, $T) << 8) + + (next_8!($byte_code, $T) << 16) + + (next_8!($byte_code, $T) << 24) + + (next_8!($byte_code, $T) << 32) + + (next_8!($byte_code, $T) << 40) + + (next_8!($byte_code, $T) << 48) + + (next_8!($byte_code, $T) << 56) + }; +} + +macro_rules! read_string { + ( $iter: expr ) => {{ + let str_length = next_32_le!($iter, usize); + let mut str_raw: Vec = Vec::new(); + let mut i = 0; + while i < str_length { + str_raw.push($iter.next().unwrap()); + i += 1; + } + String::from_utf8(str_raw).unwrap() + }}; +} + +macro_rules! write_string { + ( $raw_ptr: expr, $s: expr ) => { + for (i, b) in $s.bytes().enumerate() { + unsafe { + $raw_ptr.add(i).write(b); + } + } + }; +} + +macro_rules! write_bytes { + ( $ptr: expr, $offset: expr, $src: expr ) => { + for (i, &b) in $src.iter().enumerate() { + unsafe { + $ptr.add($offset + i).write(b); + } + } + }; +} + +pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8]) { + let mut iter = byte_code.iter().cloned(); + while let Some(op_code) = iter.next() { + match op_code { + MOV_INT => { + let target_register = next_8!(iter, usize); + let operand = next_32_le!(iter, u32) as i32; + state + .registers + .insert(target_register, DvmValue::Int(operand)); + } + MOV_LONG => { + let target_register = next_8!(iter, usize); + let operand = next_64_le!(iter, u64) as i64; + state + .registers + .insert(target_register, DvmValue::Long(operand)); + } + MOV_DOUBLE => { + let target_register = next_8!(iter, usize); + let operand = next_64_le!(iter, u64) as f64; + state + .registers + .insert(target_register, DvmValue::Double(operand)); + } + MOV_REGISTER => { + let target_register = next_8!(iter, usize); + let source_register = next_8!(iter, usize); + let source_value = state.registers.get(source_register).unwrap(); + state + .registers + .insert(target_register, source_value.clone()) + } + ALLOC => { + let target_register = next_8!(iter, usize); + let alloc_size = next_32_le!(iter, usize); + let impl_name = read_string!(iter); + + let implementation = context + .libs + .iter() + .find_map(|lib| { + lib.implementations + .iter() + .find(|implementation| implementation.fqn == impl_name) + }) + .expect(&format!("Implementation not found: {}", impl_name)); + + let dm_alloc_object = DmAllocObject::new(alloc_size, implementation.clone()); + let dvm_pointer = DvmValue::Pointer(Rc::new(dm_alloc_object)); + state.registers.insert(target_register, dvm_pointer); + } + DEALLOC => { + let target_register = next_8!(iter, usize); + let dm_alloc_object = state.registers + .remove(target_register) + .expect_pointer(); + drop(dm_alloc_object); // explicit + } + MOV_INT_TO => { + let target_register = next_8!(iter, usize); + let offset = next_32_le!(iter, usize); + let operand = next_32_le!(iter, u32) as i32; + + let dm_alloc_object = state + .registers + .get(target_register) + .unwrap() + .expect_pointer(); + write_bytes!(dm_alloc_object.data, offset, operand.to_ne_bytes()); + } + MOV_LONG_TO => { + todo!() + } + MOV_DOUBLE_TO => { + todo!() + } + MOV_REGISTER_TO => { + // Moves the value from the source register to the object pointed to by the target + // register, at the given offset. + let target_register = next_8!(iter, usize); + let offset = next_32_le!(iter, usize); + let source_register = next_8!(iter, usize); + + let target_alloc_object = state + .registers + .get(target_register) + .unwrap() + .expect_pointer(); + + let source_value = state.registers.get(source_register).unwrap(); + 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::Pointer(source_alloc_object) => { + let source_ptr = Rc::into_raw(source_alloc_object.clone()); + write_bytes!( + target_alloc_object.data, + offset, + (source_ptr as usize).to_ne_bytes() + ); + } + DvmValue::Uninit => { + panic!("Cannot move DvmValue::Uninit to object.") + } + } + } + MOV_CONST => { + // TODO: reduce the complexity of this. + // Perhaps the target register should just contain a ptr where the data is written. + + // Decode + let target_register = next_8!(iter, usize); // must contain an allocated StringImpl + let lib_name = read_string!(iter); + let const_id = next_8!(iter, usize); + let pointer_impl_register = next_8!(iter, usize); + let byte_array_impl_register = next_8!(iter, usize); + + // Get constant + let Some(lib) = context.libs.iter().find(|lib| lib.name == lib_name) else { + panic!("Could not find lib with name: {}", lib_name); + }; + let constant = lib.constants.get(const_id).unwrap(); + let DmConstant::String(s) = constant; + + // Get allocated PointerImpl + let pointer_impl = state + .registers + .get(pointer_impl_register) + .unwrap() + .expect_pointer(); + + // Init PointerImpl object + let pointer_impl_ctor_0_fn = context + .functions + .get("std::unsafe::PointerImpl::_ctor_0") + .expect("Could not find std::unsafe::PointerImpl::_ctor_0"); + call_fn( + state, + context, + pointer_impl_ctor_0_fn, + vec![ + DvmValue::Pointer(pointer_impl.clone()), + DvmValue::Long(s.len() as i64), + ], + ); + + // Get std::unsafe::PointerImpl.raw_address field as *mut u8 + let raw_ptr = unsafe { + get_field_value( + pointer_impl + .implementation + .get_field("raw_address", &pointer_impl) + .expect("Could not get PointerImpl.raw_address field."), + &pointer_impl, + ) + } + .expect_long() as usize as *mut u8; + + // Write the constant bytes to the raw_ptr + write_string!(raw_ptr, s); + + // Get allocated ArrayImpl from byte_array_impl_register + let byte_array_impl = state + .registers + .get(byte_array_impl_register) + .unwrap() + .expect_pointer(); + + // Init ArrayImpl + let array_ctor_0_fn = context + .functions + .get("std::core::ArrayImpl::_ctor_1") + .expect("Could not find std::core::ArrayImpl::_ctor_1"); + call_fn( + state, + context, + array_ctor_0_fn, + vec![ + DvmValue::Pointer(byte_array_impl.clone()), // self + DvmValue::Pointer(pointer_impl.clone()), // PointerImpl + DvmValue::Int(s.len() as i32), // length + ], + ); + + // Get allocated StringImpl from string_impl_register + let string_impl = state + .registers + .get(target_register) + .unwrap() + .expect_pointer(); + + // Init StringImpl + let string_impl_ctor_0_fn = context + .functions + .get("std::core::StringImpl::_ctor_0") + .expect("Could not find std::core::StringImpl::_ctor_0"); + call_fn( + state, + context, + string_impl_ctor_0_fn, + vec![ + DvmValue::Pointer(string_impl.clone()), + DvmValue::Pointer(byte_array_impl.clone()), + ], + ); + } + ALLOC_RAW => { + // Allocates a raw number of bytes, with the number of bytes determined by the + // operand + todo!() + } + ALLOC_RAW_FROM => { + // Allocates a raw number of bytes, with the number of bytes determined by the value + // of the source register + todo!() + } + PLATFORM_CALL => { + todo!() + } + INVOKE_FN => { + todo!() + } + INVOKE_VIRTUAL => { + todo!() + } + INVOKE_DYNAMIC => { + todo!() + } + RETURN_REGISTER => { + todo!() + } + MOV_SIZE_OF => { + todo!() + } + MULTIPLY => { + todo!() + } + op_code => { + panic!("Invalid op_code: {}", op_code); + } + } + } +} + impl DmVirtualMachine { pub fn new(libs: Vec) -> DmVirtualMachine { let mut vm = DmVirtualMachine { @@ -84,10 +481,12 @@ impl DmVirtualMachine { vm } + #[deprecated] pub fn get_fn_by_fqn(&self, fqn: &str) -> Option> { self.functions.get(fqn).cloned() } + #[deprecated] pub fn call_fn(&mut self, dm_function: &DmFn, args: Vec) -> Option { // save current state self.call_stack.push(CallFrame::DeimosCall(DeimosCallFrame { @@ -98,7 +497,7 @@ impl DmVirtualMachine { // zero registers and make sure there are enough for dm_function self.registers.clear(); if self.registers.len() < args.len() { - self.registers.resize(args.len(), DvmValue::Unit); + self.registers.resize(args.len(), DvmValue::Uninit); } // push args @@ -127,7 +526,7 @@ impl DmVirtualMachine { match code[i] { MOV_INT => { let target_register = code[i + 1] as usize; - let operand = get_32_le!(code, i, 2, u32); + let operand = next_32_le!(code, i, 2, u32); self.registers .insert(target_register, DvmValue::Int(operand as i32)); i += 6; @@ -153,9 +552,9 @@ impl DmVirtualMachine { i += 1; let target_register = code[i] as usize; i += 1; - let alloc_size = get_32_le!(code, i, 0, usize); + let alloc_size = next_32_le!(code, i, 0, usize); i += 4; - let raw_implementation_name_length = get_32_le!(code, i, 0, usize); + let raw_implementation_name_length = next_32_le!(code, i, 0, usize); i += 4; let raw_implementation_name_bytes = code[i..(i + raw_implementation_name_length)].to_vec(); @@ -201,7 +600,7 @@ impl DmVirtualMachine { i += 1; let target_register = code[i] as usize; i += 1; - let offset = get_32_le!(code, i, 0, isize); + let offset = next_32_le!(code, i, 0, isize); i += 4; let source_register = code[i] as usize; i += 1; @@ -228,11 +627,11 @@ impl DmVirtualMachine { i += 1; let target_register = code[i] as usize; i += 1; - let lib_name_length = get_32_le!(code, i, 0, usize); + let lib_name_length = next_32_le!(code, i, 0, usize); i += 4; let lib_name_raw = code[i..(i + lib_name_length)].to_vec(); i += lib_name_length; - let const_id = get_32_le!(code, i, 0, usize); + let const_id = next_32_le!(code, i, 0, usize); i += 4; let lib_name = String::from_utf8(lib_name_raw).unwrap(); @@ -241,17 +640,22 @@ impl DmVirtualMachine { let constant = &lib.constants[const_id]; match constant { DmConstant::String(s) => { - let alloc_fn = self.get_fn_by_fqn("std::unsafe::mem::alloc") + let alloc_fn = self + .get_fn_by_fqn("std::unsafe::mem::alloc") .expect("Could not find std::unsafe::mem::alloc"); let alloc_size_arg = DvmValue::Long(s.len() as i64); - let alloc_return_value = self.call_fn(&alloc_fn, vec![alloc_size_arg]).unwrap(); + let alloc_return_value = + self.call_fn(&alloc_fn, vec![alloc_size_arg]).unwrap(); let DvmValue::Pointer(pointer_object) = alloc_return_value else { panic!("Expected std::unsafe::mem::alloc to return DvmValue::Pointer, but got: {:?}", alloc_return_value); }; - let raw_address_field = pointer_object.implementation.get_field("raw_address", &pointer_object) + let raw_address_field = pointer_object + .implementation + .get_field("raw_address", &pointer_object) .expect("Could not get PointerImpl.raw_address field."); unsafe { - let raw_address_value = get_field_value(&raw_address_field, &pointer_object); + let raw_address_value = + get_field_value(&raw_address_field, &pointer_object); let DvmValue::Long(raw_address) = raw_address_value else { panic!("Expected PointerImpl.raw_address to be a DvmValue::Long, but got: {:?}", raw_address_value); }; @@ -259,7 +663,8 @@ impl DmVirtualMachine { for (j, b) in s.bytes().enumerate() { ptr.offset(j as isize).write(b); } - self.registers.insert(target_register, DvmValue::Pointer(pointer_object)); + self.registers + .insert(target_register, DvmValue::Pointer(pointer_object)); } } _ => { @@ -273,7 +678,7 @@ impl DmVirtualMachine { PLATFORM_CALL => { i += 1; - let symbol_name_length = get_32_le!(code, i, 0, usize); + let symbol_name_length = next_32_le!(code, i, 0, usize); i += 4; let symbol_name_raw = code[i..(i + symbol_name_length)].to_vec(); @@ -313,7 +718,7 @@ impl DmVirtualMachine { } INVOKE_METHOD => { i += 1; - let name_length = get_32_le!(code, i, 0, usize); + let name_length = next_32_le!(code, i, 0, usize); i += 4; let name_raw = code[i..(i + name_length)].to_vec(); i += name_length; @@ -394,7 +799,7 @@ mod dvm_run_tests { add_mov_int(&mut code, 1, 1); add_mov_register(&mut code, 0, 1); let mut vm = DmVirtualMachine::new(Vec::new()); - vm.registers.resize(2, DvmValue::Unit); + vm.registers.resize(2, DvmValue::Uninit); vm.run_raw(&code); assert_register!(DvmValue::Int(1), vm.registers.get(0)); } @@ -424,6 +829,6 @@ mod dvm_run_tests { add_dealloc(&mut code, 0); let mut vm = DmVirtualMachine::new(Vec::new()); vm.run_raw(&code); - assert_register!(DvmValue::Unit, vm.registers.get(0)); + assert_register!(DvmValue::Uninit, vm.registers.get(0)); } } diff --git a/src/vm/object_type.rs b/src/vm/object_type.rs index bd11694..0aaf676 100644 --- a/src/vm/object_type.rs +++ b/src/vm/object_type.rs @@ -15,15 +15,17 @@ pub struct DmFn { pub short_name: String, pub byte_code: Vec, pub number_used_registers: usize, + return_register: u8 } impl DmFn { - pub fn new(fqn: &str, short_name: &str, byte_code: Vec, number_used_registers: usize) -> Self { + pub fn new(fqn: &str, short_name: &str, byte_code: Vec, number_used_registers: usize, return_register: u8) -> Self { DmFn { fqn: fqn.to_string(), short_name: short_name.to_string(), byte_code, - number_used_registers + number_used_registers, + return_register } } @@ -42,6 +44,10 @@ impl DmFn { pub fn number_used_registers(&self) -> usize { self.number_used_registers } + + pub fn return_register(&self) -> u8 { + self.return_register + } } impl PartialEq for DmFn { diff --git a/src/vm/op_codes.rs b/src/vm/op_codes.rs index 89d0d50..ffb9704 100644 --- a/src/vm/op_codes.rs +++ b/src/vm/op_codes.rs @@ -45,10 +45,8 @@ pub const ALLOC_RAW_FROM: u8 = 0x0d; pub const PLATFORM_CALL: u8 = 0x10; pub const INVOKE_FN: u8 = 0x11; pub const INVOKE_VIRTUAL: u8 = 0x12; -pub const INVOKE_METHOD: u8 = 0x13; pub const INVOKE_DYNAMIC: u8 = 0x14; -pub const RETURN: u8 = 0x20; pub const RETURN_REGISTER: u8 = 0x21; pub const MOV_SIZE_OF: u8 = 0x30; @@ -159,20 +157,6 @@ pub fn add_invoke_fn(code: &mut Vec, fn_name: &str, return_register: u8, arg } } -pub fn add_invoke_method(code: &mut Vec, name: &str, arg_registers: &[u8]) { - code.push(INVOKE_METHOD); - push_number!(code, name.len() as u32); - push_string!(code, name); - push_number!(code, arg_registers.len() as u8); - for &b in arg_registers { - code.push(b); - } -} - -pub fn add_ret(code: &mut Vec) { - code.push(RETURN); -} - pub fn add_ret_register(code: &mut Vec, register: u8) { code.push(RETURN_REGISTER); code.push(register); diff --git a/src/vm/platform/std_lib/core.rs b/src/vm/platform/std_lib/core.rs index 419fd71..da7ed8c 100644 --- a/src/vm/platform/std_lib/core.rs +++ b/src/vm/platform/std_lib/core.rs @@ -5,22 +5,22 @@ use std::rc::Rc; pub fn dm_print(args: Vec, vm: &mut DmVirtualMachine) -> DvmValue { if args.len() != 1 { - return DvmValue::Unit; // TODO: make exception + return DvmValue::Uninit; // TODO: make exception } unsafe { print!("{}", get_string(&args[0], vm)); } - DvmValue::Unit + DvmValue::Uninit } pub fn dm_println(args: Vec, vm: &mut DmVirtualMachine) -> DvmValue { if args.len() != 1 { - return DvmValue::Unit; + return DvmValue::Uninit; } unsafe { println!("{}", get_string(&args[0], vm)); } - DvmValue::Unit + DvmValue::Uninit } unsafe fn get_string(dvm_value: &DvmValue, vm: &mut DmVirtualMachine) -> String { @@ -31,7 +31,7 @@ unsafe fn get_string(dvm_value: &DvmValue, vm: &mut DmVirtualMachine) -> String DvmValue::Double(d) => d.to_string(), DvmValue::Boolean(b) => b.to_string(), DvmValue::Pointer(alloc_object_rc) => convert_to_string(alloc_object_rc.clone(), vm), - DvmValue::Unit => String::from("Unit"), + DvmValue::Uninit => String::from("Unit"), } } @@ -56,17 +56,22 @@ unsafe fn convert_to_string( match pointer_value { DvmValue::Pointer(pointer_object) => { if pointer_object.implementation.fqn == "std::unsafe::PointerImpl" { - let raw_address_field = pointer_object.implementation.get_field("raw_address", &pointer_object) + let raw_address_field = pointer_object + .implementation + .get_field("raw_address", &pointer_object) .expect("Could not get PointerImpl.raw_address field."); - let raw_address_value = get_field_value(raw_address_field, &alloc_object_rc); - - let size_field = pointer_object.implementation.get_field("size", &alloc_object_rc) + let raw_address_value = + get_field_value(raw_address_field, &alloc_object_rc); + + let size_field = pointer_object + .implementation + .get_field("size", &alloc_object_rc) .expect("Could not get PointerImpl.size field."); let size_value = get_field_value(&size_field, &alloc_object_rc); let DvmValue::Long(size) = size_value else { panic!("Expected PointerImpl.size to be a Long"); }; - + match raw_address_value { DvmValue::Long(raw_address) => { let raw_bytes_pointer = raw_address as usize as *mut u8; @@ -76,19 +81,25 @@ unsafe fn convert_to_string( } String::from_utf8(v).unwrap() } - _ => panic!("Expected raw_address to be a Long.") + _ => panic!("Expected raw_address to be a Long."), } } else { panic!("Expected ArrayImpl.pointer to be a Pointer to PointerImpl, instead found: {:?}", pointer_object); } } - _ => panic!("Expected ArrayImpl.pointer to be a Pointer, instead found: {:?}", pointer_value) + _ => panic!( + "Expected ArrayImpl.pointer to be a Pointer, instead found: {:?}", + pointer_value + ), } } else { panic!("Expected String.bytes to be a Pointer to an ArrayImpl, instead found: {:?}", bytes_object.implementation.fqn); } } - _ => panic!("Expected String.bytes to be a Pointer, instead found: {:?}", bytes_value), + _ => panic!( + "Expected String.bytes to be a Pointer, instead found: {:?}", + bytes_value + ), } } else { todo!("what happens if we don't have a String?")