Successfully printed greeting!

This commit is contained in:
Jesse Brault 2024-12-26 23:05:59 -06:00
parent b7588b8787
commit e7a7cba26d
15 changed files with 304 additions and 436 deletions

View File

@ -1,8 +1,5 @@
ns std::core ns std::core
use std::unsafe::Pointer
use std::unsafe::mem::{alloc, pointer_of)
pub int Array<T> : Monad + Default + Empty { pub int Array<T> : Monad + Default + Empty {
const default = array::empty<Self> const default = array::empty<Self>
const empty = array::empty<Self> const empty = array::empty<Self>
@ -10,42 +7,12 @@ pub int Array<T> : Monad + Default + Empty {
length: Int length: Int
} }
impl ArrayImpl<T> : Array<T> {
fld pointer: Pointer
fld length: Int
pub unsafe ctor(length: Int) {
self.pointer = alloc(length * T::size())
self.length = length
}
pub ctor(pointer: Pointer, length: Int) {
self.pointer = pointer
self.length = length
}
pub unsafe fn set(index: Int, item: Pointer) {
pointer.offset(index * T::size()).write(item.read())
}
}
pub mod array { pub mod array {
// Usage: // Usage:
// let int_array = array::of(1, 2, 3) // let int_array = array::of(1, 2, 3)
// assert_eq(3, int_array.length) // assert_eq(3, int_array.length)
pub fn of<T>(ts: ...T): Array<T> { pub extern fn of<T>(ts: ...T): Array<T>
unsafe {
let array = ArrayImpl<T>(ts.length)
for (i, t) in ts.enumerate() {
let t_pointer = pointer_of(t)
array.set(i, t_pointer)
}
array
}
}
pub extern fn of_length<T>(length: Int, init_value: T): Array<T> pub extern fn of_length<T>(length: Int, init_value: T): Array<T>

View File

@ -1,14 +1 @@
ns std::unsafe ns std::unsafe
pub int Pointer
// 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)
}

View File

@ -2,9 +2,9 @@ use deimos::vm::dm_type::DmType;
use deimos::vm::lib::{DmConstant, DmLib}; use deimos::vm::lib::{DmConstant, DmLib};
use deimos::vm::object_type::{DmField, DmFn, DmImplementation, DmInterface, DmMethod}; use deimos::vm::object_type::{DmField, DmFn, DmImplementation, DmInterface, DmMethod};
use deimos::vm::op_codes::{ use deimos::vm::op_codes::{
add_alloc, add_alloc_raw_from, add_invoke_fn, add_mov_const, add_mov_register_to, add_alloc, add_invoke_fn, add_mov_const, add_mov_register_to, add_platform_call,
add_mov_size_of, add_multiply, add_platform_call,
}; };
use deimos::vm::platform::init_platform_functions;
use deimos::vm::{call_fn, DvmContext, DvmState}; use deimos::vm::{call_fn, DvmContext, DvmState};
use std::rc::Rc; use std::rc::Rc;
@ -14,95 +14,6 @@ fn main() {
// - call the main fn // - call the main fn
// fn main() { println "Hello, World!" } // fn main() { println "Hello, World!" }
// std/unsafe/mem lib
let mut mem_lib = DmLib::new("std/unsafe/mem");
// std::unsafe::Pointer
let pointer_int = DmInterface::new("std::unsafe::Pointer", "Pointer");
let pointer_int_rc = Rc::new(pointer_int);
// std::unsafe::PointerImpl : Pointer
let mut pointer_impl = DmImplementation::new(
"std::unsafe:PointerImpl",
"PointerImpl",
Some(pointer_int_rc.clone()),
);
let pointer_impl_raw_address = DmField::new("raw_address", DmType::Long, 0);
let pointer_impl_size = DmField::new("size", DmType::Long, 8);
// std::unsafe::PointerImpl::_ctor_0(
// r0: self
// r1: size Long
// )
// r2: raw_address Long
let mut pointer_impl_ctor_0_code: Vec<u8> = Vec::new();
add_alloc_raw_from(&mut pointer_impl_ctor_0_code, 2, 1);
add_mov_register_to(
&mut pointer_impl_ctor_0_code,
0,
pointer_impl_raw_address.data_offset() as u32,
2,
);
add_mov_register_to(
&mut pointer_impl_ctor_0_code,
0,
pointer_impl_size.data_offset() as u32,
1,
);
let pointer_impl_ctor_0_fn = DmFn::new(
"std::unsafe::PointerImpl::_ctor_0",
"_ctor_0",
pointer_impl_ctor_0_code,
3,
None,
);
let pointer_impl_ctor_0_method = DmMethod::new(pointer_impl_ctor_0_fn, None);
pointer_impl.fields.push(pointer_impl_raw_address);
pointer_impl.fields.push(pointer_impl_size);
pointer_impl
.methods
.push(Rc::new(pointer_impl_ctor_0_method));
let unsafe_pointer_impl_rc = Rc::new(pointer_impl);
mem_lib.interfaces.push(pointer_int_rc.clone());
mem_lib.implementations.push(unsafe_pointer_impl_rc.clone());
// std::unsafe::alloc(
// r0: size Long
// )
// r0: size Long
// r1: Pointer object
// r2: Void from PointerImpl::_ctor_0
// @return r1
let mut alloc_fn_code: Vec<u8> = Vec::new();
add_alloc(
&mut alloc_fn_code,
1,
unsafe_pointer_impl_rc.size_in_bytes() as u32,
"std::unsafe::PointerImpl",
);
add_invoke_fn(
&mut alloc_fn_code,
"std::unsafe::PointerImpl::_ctor_0",
2,
&[1u8, 0u8],
);
let alloc_fn = DmFn::new(
"std::unsafe::mem::alloc",
"alloc",
alloc_fn_code,
3,
Some(1),
);
mem_lib.functions.push(Rc::new(alloc_fn));
// std/core/array lib // std/core/array lib
let mut array_lib = DmLib::new("std/core/array"); let mut array_lib = DmLib::new("std/core/array");
@ -117,45 +28,31 @@ fn main() {
Some(array_int_rc.clone()), Some(array_int_rc.clone()),
); );
let array_impl_pointer_fld = DmField::new("pointer", DmType::Pointer, 0); let array_impl_ptr_address_fld = DmField::new("ptr_address", DmType::USize, 0);
let array_impl_length_fld = DmField::new("length", DmType::Int, 8); let array_impl_ptr_size_fld = DmField::new("ptr_size", DmType::USize, 8);
let array_impl_length_fld = DmField::new("length", DmType::Long, 16);
// std::core::Array::_ctor_0( array_impl.fields.push(array_impl_ptr_address_fld);
array_impl.fields.push(array_impl_ptr_size_fld);
array_impl.fields.push(array_impl_length_fld);
// std::core::ArrayImpl::_ctor_0(
// r0: self // r0: self
// r1: TypeRef element_type // r1: USize ptr_address
// r2: Int length // r2: USize ptr_size
// r3: Long length
// ) // )
// r3: r1::size()
// r4: r3 * r1
// r5: Pointer allocated pointer
let mut array_impl_ctor_0_bytecode: Vec<u8> = Vec::new(); let mut array_impl_ctor_0_bytecode: Vec<u8> = Vec::new();
add_mov_size_of(&mut array_impl_ctor_0_bytecode, 3, 1); add_mov_register_to(&mut array_impl_ctor_0_bytecode, 0, 0, 1);
add_multiply(&mut array_impl_ctor_0_bytecode, 4, 3, 1); add_mov_register_to(&mut array_impl_ctor_0_bytecode, 0, 8, 2);
add_invoke_fn( add_mov_register_to(&mut array_impl_ctor_0_bytecode, 0, 16, 3);
&mut array_impl_ctor_0_bytecode,
"std::unsafe::mem::alloc",
5,
&[4],
);
add_mov_register_to(
&mut array_impl_ctor_0_bytecode,
0,
array_impl_pointer_fld.data_offset() as u32,
5,
);
add_mov_register_to(
&mut array_impl_ctor_0_bytecode,
0,
array_impl_length_fld.data_offset() as u32,
2,
);
let array_impl_ctor_0_fn = DmFn::new( let array_impl_ctor_0_fn = DmFn::new(
"std::core::ArrayImpl::_ctor_0", "std::core::ArrayImpl::_ctor_0",
"_ctor_0", "_ctor_0",
array_impl_ctor_0_bytecode, array_impl_ctor_0_bytecode,
6, 4,
None, None,
); );
let array_impl_ctor_0_method = DmMethod::new(array_impl_ctor_0_fn, None); let array_impl_ctor_0_method = DmMethod::new(array_impl_ctor_0_fn, None);
@ -163,7 +60,8 @@ fn main() {
// Add Array and ArrayImpl to array lib // Add Array and ArrayImpl to array lib
array_lib.interfaces.push(array_int_rc.clone()); array_lib.interfaces.push(array_int_rc.clone());
array_lib.implementations.push(Rc::new(array_impl)); let array_impl_rc = Rc::new(array_impl);
array_lib.implementations.push(array_impl_rc.clone());
// std::core::String // std::core::String
let mut string_lib = DmLib::new("std/core/string"); let mut string_lib = DmLib::new("std/core/string");
@ -172,19 +70,15 @@ fn main() {
let mut string_impl = DmImplementation::new("std::core::StringImpl", "StringImpl", None); let mut string_impl = DmImplementation::new("std::core::StringImpl", "StringImpl", None);
let bytes_field = DmField::new("bytes", DmType::Pointer, 0); let bytes_field = DmField::new("bytes", DmType::Object, 0);
string_impl.fields.push(bytes_field);
// std::core::String::_ctor_0( // std::core::String::_ctor_0(
// r0: self // r0: self
// r1: DvmPointer to Array<Byte> // r1: Array<Byte> bytes
// ) // )
let mut string_ctor_0_bytecode: Vec<u8> = Vec::new(); let mut string_ctor_0_bytecode: Vec<u8> = Vec::new();
add_mov_register_to( add_mov_register_to(&mut string_ctor_0_bytecode, 0, 0, 1);
&mut string_ctor_0_bytecode,
0,
bytes_field.data_offset() as u32,
1,
);
let string_ctor_0_fn = DmFn::new( let string_ctor_0_fn = DmFn::new(
"std::core::StringImpl::_ctor_0", "std::core::StringImpl::_ctor_0",
@ -196,7 +90,6 @@ fn main() {
let string_ctor_0_method = DmMethod::new(string_ctor_0_fn, None); let string_ctor_0_method = DmMethod::new(string_ctor_0_fn, None);
string_impl.fields.push(bytes_field);
string_impl.methods.push(Rc::new(string_ctor_0_method)); string_impl.methods.push(Rc::new(string_ctor_0_method));
let core_string_impl_size = string_impl.size_in_bytes(); let core_string_impl_size = string_impl.size_in_bytes();
@ -207,41 +100,62 @@ fn main() {
let mut greeting_lib = DmLib::new("greeting"); let mut greeting_lib = DmLib::new("greeting");
greeting_lib greeting_lib
.constants .constants
.push(DmConstant::String("Hello, World!".to_string())); .push(DmConstant::String("Hello, Jeanna!".to_string()));
let mut main_byte_code = Vec::new(); let mut main_byte_code = Vec::new();
// 1. Move constant: r0 receives DvmValue::Pointer to ArrayImpl<Byte> // Move greeting
// 2. Allocate for std::core::StringImpl into r1 // r0: greeting address
// 3. Call StringImpl::_ctor_0(r0) -> r2 // r1: greeting size
// 4. Platform call std::core::println(r1) -> r3 add_mov_const(&mut main_byte_code, 0, 1, "greeting", 0);
// Alloc Array<Byte> greeting bytes
add_alloc( add_alloc(
&mut main_byte_code, &mut main_byte_code,
0, 2,
array_impl_rc.size_in_bytes() as u32,
"std::core::ArrayImpl",
);
// Call ArrayImpl(ptr_address, ptr_size, length)
add_invoke_fn(
&mut main_byte_code,
"std::core::ArrayImpl::_ctor_0",
3,
&[2, 0, 1, 1],
);
// Alloc StringImpl greeting
add_alloc(
&mut main_byte_code,
4,
core_string_impl_size as u32, core_string_impl_size as u32,
"std::core::StringImpl", "std::core::StringImpl",
); );
add_mov_const(&mut main_byte_code, 1, "greeting", 0);
// Call StringImpl(greeting_bytes)
add_invoke_fn( add_invoke_fn(
&mut main_byte_code, &mut main_byte_code,
"std::core::StringImpl::_ctor_0", "std::core::StringImpl::_ctor_0",
2, 5,
&[0, 1], &[4, 2],
); );
add_platform_call(&mut main_byte_code, "std::core::println", 3, 1, &vec![0u8]);
let main_dm_fn = DmFn::new("main", "main", main_byte_code, 2, None); // Call println(greeting)
add_platform_call(&mut main_byte_code, "std::core::println", 6, &[4]);
let main_dm_fn = DmFn::new("main", "main", main_byte_code, 7, None);
greeting_lib.functions.push(Rc::new(main_dm_fn)); greeting_lib.functions.push(Rc::new(main_dm_fn));
let mut state = DvmState::new(); let mut state = DvmState::new();
let mut context = DvmContext::new(); let mut context = DvmContext::new();
context.load(vec![ context.load_libs(vec![
Rc::new(greeting_lib), Rc::new(greeting_lib),
Rc::new(string_lib), Rc::new(string_lib),
Rc::new(array_lib), Rc::new(array_lib),
Rc::new(mem_lib)
]); ]);
context.load_platform_fns(&init_platform_functions());
let main_fn = context.fn_by_fqn("main").unwrap(); let main_fn = context.fn_by_fqn("main").unwrap();
call_fn(&mut state, &context, &main_fn, vec![]); call_fn(&mut state, &context, &main_fn, vec![]);

View File

@ -1,49 +1,49 @@
// use crate::util::trie::GetEdgeResult::{EdgeKeyIsPrefix, EqualKeys, KeyIsPrefix}; // use crate::util::trie::GetEdgeResult::{EdgeKeyIsPrefix, EqualKeys, KeyIsPrefix};
// use std::collections::HashMap; // use std::collections::HashMap;
// use std::rc::Rc; // use std::rc::Rc;
// //
// pub struct RadixTrie<T> { // pub struct RadixTrie<T> {
// root: RadixTrieNode<T>, // root: RadixTrieNode<T>,
// } // }
// //
// struct RadixTrieNode<T> { // struct RadixTrieNode<T> {
// edges: HashMap<String, RadixTrieNode<T>>, // edges: HashMap<String, RadixTrieNode<T>>,
// value: Option<Rc<T>>, // value: Option<Rc<T>>,
// } // }
// //
// impl<T> RadixTrie<T> { // impl<T> RadixTrie<T> {
// pub fn new() -> Self { // pub fn new() -> Self {
// RadixTrie { // RadixTrie {
// root: Default::default(), // root: Default::default(),
// } // }
// } // }
// //
// pub fn insert(&mut self, key: &str, value: &Rc<T>) { // pub fn insert(&mut self, key: &str, value: &Rc<T>) {
// self.root.insert_helper(key, value); // self.root.insert_helper(key, value);
// } // }
// //
// pub fn remove(&mut self, key: &str) { // pub fn remove(&mut self, key: &str) {
// todo!() // todo!()
// } // }
// //
// pub fn find(&self, key: &str) -> Option<Rc<T>> { // pub fn find(&self, key: &str) -> Option<Rc<T>> {
// todo!() // todo!()
// } // }
// } // }
// //
// impl<T> Default for RadixTrieNode<T> { // impl<T> Default for RadixTrieNode<T> {
// fn default() -> Self { // fn default() -> Self {
// RadixTrieNode::new() // RadixTrieNode::new()
// } // }
// } // }
// //
// enum GetEdgeResult<'a, T> { // enum GetEdgeResult<'a, T> {
// EqualKeys, // EqualKeys,
// KeyIsPrefix(&'a str, &'a mut RadixTrieNode<T>), // common prefix and target node // KeyIsPrefix(&'a str, &'a mut RadixTrieNode<T>), // common prefix and target node
// EdgeKeyIsPrefix(&'a str, &'a mut RadixTrieNode<T>), // non-common suffix and target node, // EdgeKeyIsPrefix(&'a str, &'a mut RadixTrieNode<T>), // non-common suffix and target node,
// None, // None,
// } // }
// //
// impl<T> RadixTrieNode<T> { // impl<T> RadixTrieNode<T> {
// fn new() -> Self { // fn new() -> Self {
// RadixTrieNode { // RadixTrieNode {
@ -51,14 +51,14 @@
// value: None, // value: None,
// } // }
// } // }
// //
// fn get_edge<'a>(&'a mut self, key: &'a str) -> GetEdgeResult<'a, T> { // fn get_edge<'a>(&'a mut self, key: &'a str) -> GetEdgeResult<'a, T> {
// for (edge_key, edge_node) in self.edges.iter_mut() { // for (edge_key, edge_node) in self.edges.iter_mut() {
// // Case: edge_key == key: overwrite data // // Case: edge_key == key: overwrite data
// if *key == *edge_key { // if *key == *edge_key {
// return EqualKeys; // return EqualKeys;
// } // }
// //
// // Find how many common characters there are starting from the beginning and terminating // // Find how many common characters there are starting from the beginning and terminating
// // as soon as there is no match // // as soon as there is no match
// let mut i = 0; // let mut i = 0;
@ -71,28 +71,28 @@
// break 'number_of_common_chars; // break 'number_of_common_chars;
// } // }
// } // }
// //
// // Case: key's first char does not match at all: continue searching // // Case: key's first char does not match at all: continue searching
// if i == 0 { // if i == 0 {
// continue; // continue;
// } // }
// //
// // Case: key is prefix of edge_key // // Case: key is prefix of edge_key
// if i < edge_key.len() { // if i < edge_key.len() {
// return KeyIsPrefix(key, edge_node); // return KeyIsPrefix(key, edge_node);
// } // }
// //
// if i == edge_key.len() { // if i == edge_key.len() {
// panic!( // panic!(
// "Should not have gotten here: counted common chars equals edge_key's length." // "Should not have gotten here: counted common chars equals edge_key's length."
// ) // )
// } // }
// //
// return EdgeKeyIsPrefix(&edge_key[i..], edge_node); // return EdgeKeyIsPrefix(&edge_key[i..], edge_node);
// } // }
// GetEdgeResult::None // GetEdgeResult::None
// } // }
// //
// fn insert_helper(&mut self, key: &str, value: &Rc<T>) { // fn insert_helper(&mut self, key: &str, value: &Rc<T>) {
// match self.get_edge(key) { // match self.get_edge(key) {
// EqualKeys => { // EqualKeys => {
@ -102,8 +102,8 @@
// KeyIsPrefix(prefix, edge_node) => { // KeyIsPrefix(prefix, edge_node) => {
// // split like asparagus break // // split like asparagus break
// let old_target_node = self.edges.remove(key).unwrap(); // let old_target_node = self.edges.remove(key).unwrap();
// //
// //
// let mut common_prefix_node: RadixTrieNode<T> = RadixTrieNode::new(); // let mut common_prefix_node: RadixTrieNode<T> = RadixTrieNode::new();
// } // }
// EdgeKeyIsPrefix(suffix, edge_node) => { // EdgeKeyIsPrefix(suffix, edge_node) => {

View File

@ -5,7 +5,8 @@ pub enum DmType {
Long, Long,
Double, Double,
Boolean, Boolean,
Pointer, Object,
USize,
Unit, Unit,
} }
@ -17,7 +18,8 @@ impl DmType {
DmType::Long => size_of::<i64>(), DmType::Long => size_of::<i64>(),
DmType::Double => size_of::<f64>(), DmType::Double => size_of::<f64>(),
DmType::Boolean => size_of::<bool>(), DmType::Boolean => size_of::<bool>(),
DmType::Pointer => size_of::<usize>(), DmType::Object => size_of::<usize>(),
DmType::USize => size_of::<usize>(),
DmType::Unit => todo!("Need to determine size of Unit... is it dependent on the size of the thing which is Unit?") DmType::Unit => todo!("Need to determine size of Unit... is it dependent on the size of the thing which is Unit?")
} }
} }

View File

@ -1,4 +1,4 @@
use crate::vm::mem::DmAllocObject; use crate::vm::object::DmAllocObject;
use std::rc::Rc; use std::rc::Rc;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -8,7 +8,8 @@ pub enum DvmValue {
Long(i64), Long(i64),
Double(f64), Double(f64),
Boolean(bool), Boolean(bool),
Pointer(Rc<DmAllocObject>), Object(Rc<DmAllocObject>),
USize(usize),
Uninit, Uninit,
Void, Void,
} }
@ -18,15 +19,23 @@ impl DvmValue {
if let DvmValue::Long(l) = self { if let DvmValue::Long(l) = self {
*l *l
} else { } else {
panic!("Expected DvmValue::Long, but found {:?}", self) panic!("Expected DvmValue::Long, but found DvmValue::{:?}", self)
} }
} }
pub fn expect_pointer(&self) -> Rc<DmAllocObject> { pub fn expect_object(&self) -> Rc<DmAllocObject> {
if let DvmValue::Pointer(p) = self { if let DvmValue::Object(o) = self {
p.clone() o.clone()
} else { } else {
panic!("Expected DvmValue::Pointer, but found {:?}", self); panic!("Expected DvmValue::Object, but found DvmValue::{:?}", self);
}
}
pub fn expect_usize(&self) -> usize {
if let DvmValue::USize(u) = self {
*u
} else {
panic!("Expected DvmValue::USize, but found DvmValue::{:?}", self);
} }
} }
} }

View File

@ -1,7 +1,7 @@
use crate::get_32_le; use crate::get_32_le;
use crate::vm::lib::DmLib;
use crate::vm::lib::magic::{CONST_SYMBOL, DEIMOS_MAGIC_NUMBER, FUNCTION_SYMBOL}; use crate::vm::lib::magic::{CONST_SYMBOL, DEIMOS_MAGIC_NUMBER, FUNCTION_SYMBOL};
use crate::vm::lib::symbol::LibSymbol; use crate::vm::lib::symbol::LibSymbol;
use crate::vm::lib::DmLib;
pub fn load_module(bytes: &[u8]) -> Result<DmLib, String> { pub fn load_module(bytes: &[u8]) -> Result<DmLib, String> {
let mut ip: usize = 0; let mut ip: usize = 0;

View File

@ -1,5 +1,5 @@
use crate::vm::lib::DmLib;
use crate::vm::lib::magic::{COMPILER_VERSION_STRING, DEIMOS_MAGIC_STRING}; use crate::vm::lib::magic::{COMPILER_VERSION_STRING, DEIMOS_MAGIC_STRING};
use crate::vm::lib::DmLib;
macro_rules! push_byte_array { macro_rules! push_byte_array {
( $dest: expr, $arr: expr ) => { ( $dest: expr, $arr: expr ) => {
@ -37,4 +37,4 @@ pub fn write_module(module: DmLib) -> Vec<u8> {
push_string!(result, COMPILER_VERSION_STRING); push_string!(result, COMPILER_VERSION_STRING);
result result
} }

View File

@ -1,40 +1,9 @@
use crate::vm::dm_type::DmType; use crate::vm::dm_type::DmType;
use crate::vm::dvm_value::DvmValue; use crate::vm::dvm_value::DvmValue;
use crate::vm::object_type::{DmField, DmImplementation}; use crate::vm::object::DmAllocObject;
use std::alloc::{alloc, dealloc, Layout}; use crate::vm::object_type::DmField;
use std::collections::HashSet;
use std::rc::Rc; use std::rc::Rc;
#[derive(Debug, PartialEq, Eq)]
pub struct DmAllocObject {
pub data: *mut u8,
pub units: HashSet<usize>,
pub size: usize,
pub layout: Layout,
pub implementation: Rc<DmImplementation>,
}
impl DmAllocObject {
pub fn new(size: usize, implementation: Rc<DmImplementation>) -> 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 { pub unsafe fn get_field_value(dm_field: &DmField, self_object: &DmAllocObject) -> DvmValue {
let data_size = dm_field.dm_type().size_in_bytes(); let data_size = dm_field.dm_type().size_in_bytes();
let mut raw_data: Vec<u8> = Vec::with_capacity(data_size); let mut raw_data: Vec<u8> = Vec::with_capacity(data_size);
@ -53,11 +22,14 @@ pub unsafe fn get_field_value(dm_field: &DmField, self_object: &DmAllocObject) -
raw_data[0..data_size].try_into().unwrap(), raw_data[0..data_size].try_into().unwrap(),
)), )),
DmType::Boolean => DvmValue::Boolean(raw_data[0] != 0), DmType::Boolean => DvmValue::Boolean(raw_data[0] != 0),
DmType::Pointer => { DmType::Object => {
// read the pointer's (address) value // read the pointer's (address) value
let address = usize::from_ne_bytes(raw_data[0..data_size].try_into().unwrap()); let address = usize::from_ne_bytes(raw_data[0..data_size].try_into().unwrap());
DvmValue::Pointer(Rc::from_raw(address as *const DmAllocObject)) DvmValue::Object(Rc::from_raw(address as *const DmAllocObject))
} }
DmType::USize => DvmValue::USize(usize::from_ne_bytes(
raw_data[0..data_size].try_into().unwrap(),
)),
DmType::Unit => DvmValue::Uninit, DmType::Unit => DvmValue::Uninit,
} }
} }

View File

@ -2,14 +2,16 @@ pub mod dm_type;
pub mod dvm_value; pub mod dvm_value;
pub mod lib; pub mod lib;
pub mod mem; pub mod mem;
mod object;
pub mod object_type; pub mod object_type;
pub mod op_codes; pub mod op_codes;
pub mod platform; pub mod platform;
mod pointer;
pub mod util; pub mod util;
use crate::vm::dvm_value::DvmValue; use crate::vm::dvm_value::DvmValue;
use crate::vm::lib::{DmConstant, DmLib}; use crate::vm::lib::{DmConstant, DmLib};
use crate::vm::mem::{get_field_value, DmAllocObject}; use crate::vm::object::DmAllocObject;
use crate::vm::object_type::DmFn; use crate::vm::object_type::DmFn;
use op_codes::*; use op_codes::*;
use std::alloc::{alloc, dealloc, Layout}; use std::alloc::{alloc, dealloc, Layout};
@ -19,13 +21,15 @@ use std::rc::Rc;
pub type PlatformFunction = pub type PlatformFunction =
fn(args: Vec<DvmValue>, state: &mut DvmState, context: &DvmContext) -> DvmValue; fn(args: Vec<DvmValue>, state: &mut DvmState, context: &DvmContext) -> DvmValue;
#[derive(Debug)]
enum CallFrame { enum CallFrame {
PlatformCall(CallFrameInfo), PlatformCall(CallFrameInfo),
DeimosCall(CallFrameInfo), DeimosCall(CallFrameInfo),
} }
#[derive(Debug)]
struct CallFrameInfo { struct CallFrameInfo {
fn_fqn: String, pub fqn: String,
} }
pub struct DvmContext { pub struct DvmContext {
@ -43,7 +47,7 @@ impl DvmContext {
} }
} }
pub fn load(&mut self, libs: Vec<Rc<DmLib>>) { pub fn load_libs(&mut self, libs: Vec<Rc<DmLib>>) {
for lib in libs { for lib in libs {
self.libs.push(lib.clone()); self.libs.push(lib.clone());
for lib_fn in &lib.functions { for lib_fn in &lib.functions {
@ -75,14 +79,19 @@ impl DvmContext {
.iter() .iter()
.flat_map(|implementation| &implementation.methods) .flat_map(|implementation| &implementation.methods)
{ {
self.functions.insert( self.functions
method.dm_fn().fqn().to_string(), .insert(method.dm_fn().fqn().to_string(), method.dm_fn().clone());
method.dm_fn().clone(),
);
} }
} }
} }
pub fn load_platform_fns(&mut self, platform_fns: &HashMap<String, PlatformFunction>) {
for (fqn, platform_fn) in platform_fns {
self.platform_functions
.insert(fqn.to_string(), Rc::new(*platform_fn));
}
}
pub fn fn_by_fqn(&self, fqn: &str) -> Option<Rc<DmFn>> { pub fn fn_by_fqn(&self, fqn: &str) -> Option<Rc<DmFn>> {
self.functions.get(fqn).cloned() self.functions.get(fqn).cloned()
} }
@ -108,6 +117,30 @@ impl DvmState {
} }
} }
macro_rules! dump_state {
( $message: expr, $state: expr ) => {
println!("----");
println!("{}", $message);
println!("----");
println!("Call stack:");
for call_frame in &$state.call_stack {
match call_frame {
CallFrame::PlatformCall(frame_info) => {
println!(" {}", frame_info.fqn);
}
CallFrame::DeimosCall(frame_info) => {
println!(" {}", frame_info.fqn);
}
}
}
println!("Registers: ");
for (i, register) in $state.registers.iter().enumerate() {
println!(" r{}: {:?}", i, register);
}
};
}
pub fn call_fn( pub fn call_fn(
state: &mut DvmState, state: &mut DvmState,
context: &DvmContext, context: &DvmContext,
@ -116,7 +149,7 @@ pub fn call_fn(
) -> DvmValue { ) -> DvmValue {
// save current state // save current state
state.call_stack.push(CallFrame::DeimosCall(CallFrameInfo { state.call_stack.push(CallFrame::DeimosCall(CallFrameInfo {
fn_fqn: dm_fn.fqn().to_string(), fqn: dm_fn.fqn().to_string(),
})); }));
state.register_state_stack.push(state.registers.clone()); state.register_state_stack.push(state.registers.clone());
@ -129,8 +162,8 @@ pub fn call_fn(
} }
// push args // push args
for arg in args { for (i, arg) in args.iter().enumerate() {
state.registers.push(arg); state.registers[i] = arg.clone();
} }
// run the byte code // run the byte code
@ -233,31 +266,23 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
MOV_INT => { MOV_INT => {
let target_register = next_8!(iter, usize); let target_register = next_8!(iter, usize);
let operand = next_32_le!(iter, u32) as i32; let operand = next_32_le!(iter, u32) as i32;
state state.registers[target_register] = DvmValue::Int(operand);
.registers
.insert(target_register, DvmValue::Int(operand));
} }
MOV_LONG => { MOV_LONG => {
let target_register = next_8!(iter, usize); let target_register = next_8!(iter, usize);
let operand = next_64_le!(iter, u64) as i64; let operand = next_64_le!(iter, u64) as i64;
state state.registers[target_register] = DvmValue::Long(operand);
.registers
.insert(target_register, DvmValue::Long(operand));
} }
MOV_DOUBLE => { MOV_DOUBLE => {
let target_register = next_8!(iter, usize); let target_register = next_8!(iter, usize);
let operand = next_64_le!(iter, u64) as f64; let operand = next_64_le!(iter, u64) as f64;
state state.registers[target_register] = DvmValue::Double(operand);
.registers
.insert(target_register, DvmValue::Double(operand));
} }
MOV_REGISTER => { MOV_REGISTER => {
let target_register = next_8!(iter, usize); let target_register = next_8!(iter, usize);
let source_register = next_8!(iter, usize); let source_register = next_8!(iter, usize);
let source_value = state.registers.get(source_register).unwrap(); let source_value = state.registers.get(source_register).unwrap();
state state.registers[target_register] = source_value.clone();
.registers
.insert(target_register, source_value.clone())
} }
ALLOC => { ALLOC => {
let target_register = next_8!(iter, usize); let target_register = next_8!(iter, usize);
@ -275,13 +300,17 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
.expect(&format!("Implementation not found: {}", impl_name)); .expect(&format!("Implementation not found: {}", impl_name));
let dm_alloc_object = DmAllocObject::new(alloc_size, implementation.clone()); let dm_alloc_object = DmAllocObject::new(alloc_size, implementation.clone());
let dvm_pointer = DvmValue::Pointer(Rc::new(dm_alloc_object)); state.registers[target_register] = DvmValue::Object(Rc::new(dm_alloc_object));
state.registers.insert(target_register, dvm_pointer);
} }
DEALLOC => { DEALLOC => {
let target_register = next_8!(iter, usize); let target_register = next_8!(iter, usize);
let dm_alloc_object = state.registers.remove(target_register).expect_pointer(); let dm_alloc_object = state
.registers
.get(target_register)
.unwrap()
.expect_object();
drop(dm_alloc_object); // explicit drop(dm_alloc_object); // explicit
state.registers[target_register] = DvmValue::Uninit;
} }
MOV_INT_TO => { MOV_INT_TO => {
let target_register = next_8!(iter, usize); let target_register = next_8!(iter, usize);
@ -292,7 +321,7 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
.registers .registers
.get(target_register) .get(target_register)
.unwrap() .unwrap()
.expect_pointer(); .expect_object();
write_bytes!(dm_alloc_object.data, offset, operand.to_ne_bytes()); write_bytes!(dm_alloc_object.data, offset, operand.to_ne_bytes());
} }
MOV_LONG_TO => { MOV_LONG_TO => {
@ -312,7 +341,7 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
.registers .registers
.get(target_register) .get(target_register)
.unwrap() .unwrap()
.expect_pointer(); .expect_object();
let source_value = state.registers.get(source_register).unwrap(); let source_value = state.registers.get(source_register).unwrap();
match source_value { match source_value {
@ -331,14 +360,17 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
DvmValue::Boolean(b) => unsafe { DvmValue::Boolean(b) => unsafe {
target_alloc_object.data.add(offset).write(*b as u8); target_alloc_object.data.add(offset).write(*b as u8);
}, },
DvmValue::Pointer(source_alloc_object) => { DvmValue::Object(source_object) => {
let source_ptr = Rc::into_raw(source_alloc_object.clone()); let source_object_ptr = Rc::into_raw(source_object.clone());
write_bytes!( write_bytes!(
target_alloc_object.data, target_alloc_object.data,
offset, offset,
(source_ptr as usize).to_ne_bytes() (source_object_ptr as usize).to_ne_bytes()
); );
} }
DvmValue::USize(us) => {
write_bytes!(target_alloc_object.data, offset, us.to_ne_bytes());
}
DvmValue::Uninit => { DvmValue::Uninit => {
panic!("Cannot move DvmValue::Uninit to object.") panic!("Cannot move DvmValue::Uninit to object.")
} }
@ -348,15 +380,11 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
} }
} }
MOV_CONST => { MOV_CONST => {
// TODO: reduce the complexity of this.
// Perhaps the target register should just contain a ptr where the data is written.
// Decode // Decode
let target_register = next_8!(iter, usize); // must contain an allocated StringImpl let address_register = next_8!(iter, usize);
let size_register = next_8!(iter, usize);
let lib_name = read_string!(iter); let lib_name = read_string!(iter);
let const_id = next_8!(iter, usize); let const_id = next_32_le!(iter, usize);
let pointer_impl_register = next_8!(iter, usize);
let byte_array_impl_register = next_8!(iter, usize);
// Get constant // Get constant
let Some(lib) = context.libs.iter().find(|lib| lib.name == lib_name) else { let Some(lib) = context.libs.iter().find(|lib| lib.name == lib_name) else {
@ -365,118 +393,49 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
let constant = lib.constants.get(const_id).unwrap(); let constant = lib.constants.get(const_id).unwrap();
let DmConstant::String(s) = constant; let DmConstant::String(s) = constant;
// Get allocated PointerImpl // Alloc memory for constant
let pointer_impl = state let size = s.len();
.registers let layout = Layout::from_size_align(size, 1).unwrap();
.get(pointer_impl_register) let raw_pointer = unsafe { alloc(layout) };
.unwrap()
.expect_pointer();
// Init PointerImpl object // Move constant to memory
let pointer_impl_ctor_0_fn = context let bytes = s.as_bytes();
.functions for i in 0..size {
.get("std::unsafe::PointerImpl::_ctor_0") unsafe {
.expect("Could not find std::unsafe::PointerImpl::_ctor_0"); raw_pointer.add(i).write(bytes[i]);
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 // Store the pointer metadata in target registers.
write_string!(raw_ptr, s); state.registers[address_register] = DvmValue::USize(raw_pointer as usize);
state.registers[size_register] = DvmValue::USize(size);
// Get allocated ArrayImpl<Byte> from byte_array_impl_register
let byte_array_impl = state
.registers
.get(byte_array_impl_register)
.unwrap()
.expect_pointer();
// Init ArrayImpl<Byte>
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 => { ALLOC_RAW => {
// Allocates a raw number of bytes, with the number of bytes determined by the value // Allocates a raw number of bytes, with the number of bytes determined by the value
// of the source register. The address is stored in the target register as a // of the source register.
// DvmValue::Long. let address_register = next_8!(iter, usize);
let target_register = next_8!(iter, usize);
let source_register = next_8!(iter, usize); let source_register = next_8!(iter, usize);
let number_of_bytes = let size = state.registers.get(source_register).unwrap().expect_long() as usize;
state.registers.get(source_register).unwrap().expect_long() as usize; let layout = Layout::from_size_align(size, 1).unwrap();
let layout = Layout::from_size_align(number_of_bytes, 0).unwrap(); let raw_ptr = unsafe { alloc(layout) };
let ptr = unsafe { alloc(layout) }; state.registers[address_register] = DvmValue::USize(raw_ptr as usize);
state
.registers
.insert(target_register, DvmValue::Long(ptr as i64))
} }
DEALLOC_RAW => { DEALLOC_RAW => {
// Deallocates a raw number of bytes at an address, with the number of bytes // Deallocates a DvmValue::Pointer(DvmPointer) in the target register.
// determined by the value in the source register, and the address stored in the let address_register = next_8!(iter, usize);
// target register. let size_register = next_8!(iter, usize);
let target_register = next_8!(iter, usize); let address = state
let source_register = next_8!(iter, usize); .registers
let number_of_bytes = .get(address_register)
state.registers.get(source_register).unwrap().expect_long() as usize; .unwrap()
.expect_usize();
let layout = Layout::from_size_align(number_of_bytes, 0).unwrap(); let size = state.registers.get(size_register).unwrap().expect_usize();
let ptr = let layout = Layout::from_size_align(size, 1).unwrap();
state.registers.get(target_register).unwrap().expect_long() as usize as *mut u8;
unsafe { unsafe {
dealloc(ptr, layout); dealloc(address as *mut u8, layout);
} }
state.registers.insert(target_register, DvmValue::Uninit); state.registers[address_register] = DvmValue::Uninit;
state.registers[size_register] = DvmValue::Uninit;
} }
PLATFORM_CALL => { PLATFORM_CALL => {
// Calls a platform function. The result of the platform call is stored in the // Calls a platform function. The result of the platform call is stored in the
@ -498,11 +457,9 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
.clone(); .clone();
state state
.call_stack .call_stack
.push(CallFrame::PlatformCall(CallFrameInfo { .push(CallFrame::PlatformCall(CallFrameInfo { fqn: symbol_name }));
fn_fqn: symbol_name,
}));
let call_result = platform_function(args, state, context); let call_result = platform_function(args, state, context);
state.registers.insert(return_register, call_result); state.registers[return_register] = call_result;
state.call_stack.pop(); state.call_stack.pop();
} }
INVOKE_FN => { INVOKE_FN => {
@ -518,7 +475,7 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
let dm_fn = context.functions.get(&symbol_name).unwrap(); let dm_fn = context.functions.get(&symbol_name).unwrap();
let call_result = call_fn(state, context, dm_fn, args); let call_result = call_fn(state, context, dm_fn, args);
state.registers.insert(return_register, call_result); state.registers[return_register] = call_result;
} }
INVOKE_VIRTUAL => { INVOKE_VIRTUAL => {
let symbol_name = read_string!(iter); let symbol_name = read_string!(iter);
@ -531,7 +488,7 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
args.push(value.clone()); args.push(value.clone());
} }
let self_obj = args.get(0).unwrap().expect_pointer(); let self_obj = args.get(0).unwrap().expect_object();
let method = self_obj let method = self_obj
.implementation .implementation
.get_method(&symbol_name, &self_obj) .get_method(&symbol_name, &self_obj)
@ -539,7 +496,7 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
let dm_fn = method.dm_fn(); let dm_fn = method.dm_fn();
let call_result = call_fn(state, context, &dm_fn, args); let call_result = call_fn(state, context, &dm_fn, args);
state.registers.insert(return_register, call_result); state.registers[return_register] = call_result;
} }
INVOKE_DYNAMIC => { INVOKE_DYNAMIC => {
unimplemented!("INVOKE_DYNAMIC is not yet supported and may never be.") unimplemented!("INVOKE_DYNAMIC is not yet supported and may never be.")

34
src/vm/object.rs Normal file
View File

@ -0,0 +1,34 @@
use crate::vm::object_type::DmImplementation;
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<usize>,
pub size: usize,
pub layout: Layout,
pub implementation: Rc<DmImplementation>,
}
impl DmAllocObject {
pub fn new(size: usize, implementation: Rc<DmImplementation>) -> 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);
}
}
}

View File

@ -1,5 +1,5 @@
use crate::vm::dm_type::DmType; use crate::vm::dm_type::DmType;
use crate::vm::mem::DmAllocObject; use crate::vm::object::DmAllocObject;
use std::fmt::Debug; use std::fmt::Debug;
use std::rc::Rc; use std::rc::Rc;

View File

@ -75,9 +75,9 @@ pub fn add_mov_register(code: &mut Vec<u8>, target_register: u8, source_register
code.push(source_register); code.push(source_register);
} }
pub fn add_alloc(code: &mut Vec<u8>, register: u8, size: u32, implementation_name: &str) { pub fn add_alloc(code: &mut Vec<u8>, target_register: u8, size: u32, implementation_name: &str) {
code.push(ALLOC); code.push(ALLOC);
code.push(register); code.push(target_register);
push_number!(code, size); push_number!(code, size);
push_number!(code, implementation_name.len() as u32); push_number!(code, implementation_name.len() as u32);
push_string!(code, implementation_name); push_string!(code, implementation_name);
@ -113,9 +113,16 @@ pub fn add_mov_register_to(
code.push(source_register); code.push(source_register);
} }
pub fn add_mov_const(code: &mut Vec<u8>, register: u8, lib_name: &str, const_id: u32) { pub fn add_mov_const(
code: &mut Vec<u8>,
address_register: u8,
size_register: u8,
lib_name: &str,
const_id: u32,
) {
code.push(MOV_CONST); code.push(MOV_CONST);
code.push(register); code.push(address_register);
code.push(size_register);
push_number!(code, lib_name.len() as u32); push_number!(code, lib_name.len() as u32);
push_string!(code, lib_name); push_string!(code, lib_name);
push_number!(code, const_id); push_number!(code, const_id);
@ -125,14 +132,13 @@ pub fn add_platform_call(
code: &mut Vec<u8>, code: &mut Vec<u8>,
symbol_name: &str, symbol_name: &str,
return_register: u8, return_register: u8,
arg_registers_length: u8, arg_registers: &[u8],
arg_registers: &Vec<u8>,
) { ) {
code.push(PLATFORM_CALL); code.push(PLATFORM_CALL);
push_number!(code, symbol_name.len() as u32); push_number!(code, symbol_name.len() as u32);
push_string!(code, symbol_name); push_string!(code, symbol_name);
push_number!(code, return_register); push_number!(code, return_register);
push_number!(code, arg_registers_length); push_number!(code, arg_registers.len() as u8);
for &b in arg_registers { for &b in arg_registers {
code.push(b); code.push(b);
} }

View File

@ -1,5 +1,6 @@
use crate::vm::dvm_value::DvmValue; use crate::vm::dvm_value::DvmValue;
use crate::vm::mem::{get_field_value, DmAllocObject}; use crate::vm::mem::get_field_value;
use crate::vm::object::DmAllocObject;
use crate::vm::{DvmContext, DvmState}; use crate::vm::{DvmContext, DvmState};
use std::rc::Rc; use std::rc::Rc;
@ -30,14 +31,15 @@ unsafe fn get_string(dvm_value: &DvmValue) -> String {
DvmValue::Long(l) => l.to_string(), DvmValue::Long(l) => l.to_string(),
DvmValue::Double(d) => d.to_string(), DvmValue::Double(d) => d.to_string(),
DvmValue::Boolean(b) => b.to_string(), DvmValue::Boolean(b) => b.to_string(),
DvmValue::Pointer(object) => convert_to_string(object.clone()), DvmValue::Object(object) => object_to_string(object.clone()),
DvmValue::USize(u) => u.to_string(),
DvmValue::Uninit => String::from("Uninit"), DvmValue::Uninit => String::from("Uninit"),
DvmValue::Void => String::from("Void"), DvmValue::Void => String::from("Void"),
} }
} }
fn convert_to_string(alloc_object_rc: Rc<DmAllocObject>) -> String { fn object_to_string(alloc_object_rc: Rc<DmAllocObject>) -> String {
if alloc_object_rc.implementation.fqn == "std::core::String" { if alloc_object_rc.implementation.fqn == "std::core::StringImpl" {
extract_string_from_string(alloc_object_rc.clone()) extract_string_from_string(alloc_object_rc.clone())
} else { } else {
todo!("what happens if we don't have a String?") todo!("what happens if we don't have a String?")
@ -49,36 +51,27 @@ fn extract_string_from_string(string_object: Rc<DmAllocObject>) -> String {
.implementation .implementation
.get_field("bytes", &string_object) .get_field("bytes", &string_object)
.expect("Could not get String.bytes field."); .expect("Could not get String.bytes field.");
let bytes_object = unsafe { get_field_value(&bytes_field, &string_object) }.expect_pointer(); let bytes_object = unsafe { get_field_value(&bytes_field, &string_object) }.expect_object();
if bytes_object.implementation.fqn != "std::core::ArrayImpl" { if bytes_object.implementation.fqn != "std::core::ArrayImpl" {
panic!("String.bytes field is not a std::core::ArrayImpl"); panic!("String.bytes field is not a std::core::ArrayImpl");
} }
let pointer_field = bytes_object let ptr_address_field = bytes_object
.implementation .implementation
.get_field("pointer", &bytes_object) .get_field("ptr_address", &bytes_object)
.expect("Could not get ArrayImpl.pointer field."); .expect("Could not get ArrayImpl.ptr_address field.");
let pointer_object = unsafe { get_field_value(&pointer_field, &bytes_object) }.expect_pointer(); let address = unsafe { get_field_value(&ptr_address_field, &bytes_object) }.expect_usize();
if pointer_object.implementation.fqn != "std::unsafe::PointerImpl" {
panic!("ArrayImpl.pointer is not a std::unsafe::PointerImpl");
}
let raw_address_field = pointer_object let ptr_size_field = bytes_object
.implementation .implementation
.get_field("raw_address", &pointer_object) .get_field("ptr_size", &bytes_object)
.expect("Could not get PointerImpl.raw_address field."); .expect("Could not get ArrayImpl.ptr_size field.");
let raw_address = unsafe { get_field_value(&raw_address_field, &pointer_object) }.expect_long(); let size = unsafe { get_field_value(&ptr_size_field, &bytes_object) }.expect_usize();
let size_field = pointer_object let raw_bytes_pointer = address as *mut u8;
.implementation
.get_field("size", &pointer_object)
.expect("Could not get PointerImpl.size field.");
let size = unsafe { get_field_value(&size_field, &pointer_object) }.expect_long();
let raw_bytes_pointer = raw_address as usize as *mut u8;
let mut v: Vec<u8> = Vec::new(); let mut v: Vec<u8> = Vec::new();
for i in 0..(size as isize) { for i in 0..size {
v.push(unsafe { raw_bytes_pointer.offset(i).read() }); v.push(unsafe { raw_bytes_pointer.add(i).read() });
} }
String::from_utf8(v).unwrap() String::from_utf8(v).unwrap()
} }

27
src/vm/pointer.rs Normal file
View File

@ -0,0 +1,27 @@
use std::fmt::{Display, Formatter};
#[derive(Debug, PartialEq, Eq)]
pub struct DvmPointer {
address: *mut u8,
size: usize,
}
impl DvmPointer {
pub fn new(address: *mut u8, size: usize) -> DvmPointer {
DvmPointer { address, size }
}
pub fn address(&self) -> *mut u8 {
self.address
}
pub fn size(&self) -> usize {
self.size
}
}
impl Display for DvmPointer {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("0x{:x}", self.address as usize))
}
}