Successfully printed greeting!
This commit is contained in:
parent
b7588b8787
commit
e7a7cba26d
@ -1,8 +1,5 @@
|
||||
ns std::core
|
||||
|
||||
use std::unsafe::Pointer
|
||||
use std::unsafe::mem::{alloc, pointer_of)
|
||||
|
||||
pub int Array<T> : Monad + Default + Empty {
|
||||
const default = array::empty<Self>
|
||||
const empty = array::empty<Self>
|
||||
@ -10,42 +7,12 @@ pub int Array<T> : Monad + Default + Empty {
|
||||
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 {
|
||||
|
||||
// Usage:
|
||||
// let int_array = array::of(1, 2, 3)
|
||||
// assert_eq(3, int_array.length)
|
||||
pub 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<T>(ts: ...T): Array<T>
|
||||
|
||||
pub extern fn of_length<T>(length: Int, init_value: T): Array<T>
|
||||
|
||||
|
@ -1,14 +1 @@
|
||||
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)
|
||||
|
||||
}
|
||||
|
@ -2,9 +2,9 @@ use deimos::vm::dm_type::DmType;
|
||||
use deimos::vm::lib::{DmConstant, DmLib};
|
||||
use deimos::vm::object_type::{DmField, DmFn, DmImplementation, DmInterface, DmMethod};
|
||||
use deimos::vm::op_codes::{
|
||||
add_alloc, add_alloc_raw_from, add_invoke_fn, add_mov_const, add_mov_register_to,
|
||||
add_mov_size_of, add_multiply, add_platform_call,
|
||||
add_alloc, add_invoke_fn, add_mov_const, add_mov_register_to, add_platform_call,
|
||||
};
|
||||
use deimos::vm::platform::init_platform_functions;
|
||||
use deimos::vm::{call_fn, DvmContext, DvmState};
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -14,95 +14,6 @@ fn main() {
|
||||
// - call the main fn
|
||||
// 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
|
||||
let mut array_lib = DmLib::new("std/core/array");
|
||||
|
||||
@ -117,45 +28,31 @@ fn main() {
|
||||
Some(array_int_rc.clone()),
|
||||
);
|
||||
|
||||
let array_impl_pointer_fld = DmField::new("pointer", DmType::Pointer, 0);
|
||||
let array_impl_length_fld = DmField::new("length", DmType::Int, 8);
|
||||
let array_impl_ptr_address_fld = DmField::new("ptr_address", DmType::USize, 0);
|
||||
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
|
||||
// r1: TypeRef element_type
|
||||
// r2: Int length
|
||||
// r1: USize ptr_address
|
||||
// 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();
|
||||
|
||||
add_mov_size_of(&mut array_impl_ctor_0_bytecode, 3, 1);
|
||||
add_multiply(&mut array_impl_ctor_0_bytecode, 4, 3, 1);
|
||||
add_invoke_fn(
|
||||
&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,
|
||||
);
|
||||
add_mov_register_to(&mut array_impl_ctor_0_bytecode, 0, 0, 1);
|
||||
add_mov_register_to(&mut array_impl_ctor_0_bytecode, 0, 8, 2);
|
||||
add_mov_register_to(&mut array_impl_ctor_0_bytecode, 0, 16, 3);
|
||||
|
||||
let array_impl_ctor_0_fn = DmFn::new(
|
||||
"std::core::ArrayImpl::_ctor_0",
|
||||
"_ctor_0",
|
||||
array_impl_ctor_0_bytecode,
|
||||
6,
|
||||
4,
|
||||
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
|
||||
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
|
||||
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 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(
|
||||
// r0: self
|
||||
// r1: DvmPointer to Array<Byte>
|
||||
// r1: Array<Byte> bytes
|
||||
// )
|
||||
let mut string_ctor_0_bytecode: Vec<u8> = Vec::new();
|
||||
add_mov_register_to(
|
||||
&mut string_ctor_0_bytecode,
|
||||
0,
|
||||
bytes_field.data_offset() as u32,
|
||||
1,
|
||||
);
|
||||
add_mov_register_to(&mut string_ctor_0_bytecode, 0, 0, 1);
|
||||
|
||||
let string_ctor_0_fn = DmFn::new(
|
||||
"std::core::StringImpl::_ctor_0",
|
||||
@ -196,7 +90,6 @@ fn main() {
|
||||
|
||||
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));
|
||||
let core_string_impl_size = string_impl.size_in_bytes();
|
||||
|
||||
@ -207,41 +100,62 @@ fn main() {
|
||||
let mut greeting_lib = DmLib::new("greeting");
|
||||
greeting_lib
|
||||
.constants
|
||||
.push(DmConstant::String("Hello, World!".to_string()));
|
||||
.push(DmConstant::String("Hello, Jeanna!".to_string()));
|
||||
|
||||
let mut main_byte_code = Vec::new();
|
||||
|
||||
// 1. Move constant: r0 receives DvmValue::Pointer to ArrayImpl<Byte>
|
||||
// 2. Allocate for std::core::StringImpl into r1
|
||||
// 3. Call StringImpl::_ctor_0(r0) -> r2
|
||||
// 4. Platform call std::core::println(r1) -> r3
|
||||
// Move greeting
|
||||
// r0: greeting address
|
||||
// r1: greeting size
|
||||
add_mov_const(&mut main_byte_code, 0, 1, "greeting", 0);
|
||||
|
||||
// Alloc Array<Byte> greeting bytes
|
||||
add_alloc(
|
||||
&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,
|
||||
"std::core::StringImpl",
|
||||
);
|
||||
add_mov_const(&mut main_byte_code, 1, "greeting", 0);
|
||||
|
||||
// Call StringImpl(greeting_bytes)
|
||||
add_invoke_fn(
|
||||
&mut main_byte_code,
|
||||
"std::core::StringImpl::_ctor_0",
|
||||
2,
|
||||
&[0, 1],
|
||||
5,
|
||||
&[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));
|
||||
|
||||
let mut state = DvmState::new();
|
||||
let mut context = DvmContext::new();
|
||||
context.load(vec![
|
||||
context.load_libs(vec![
|
||||
Rc::new(greeting_lib),
|
||||
Rc::new(string_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();
|
||||
call_fn(&mut state, &context, &main_fn, vec![]);
|
||||
|
@ -5,7 +5,8 @@ pub enum DmType {
|
||||
Long,
|
||||
Double,
|
||||
Boolean,
|
||||
Pointer,
|
||||
Object,
|
||||
USize,
|
||||
Unit,
|
||||
}
|
||||
|
||||
@ -17,7 +18,8 @@ impl DmType {
|
||||
DmType::Long => size_of::<i64>(),
|
||||
DmType::Double => size_of::<f64>(),
|
||||
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?")
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::vm::mem::DmAllocObject;
|
||||
use crate::vm::object::DmAllocObject;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
@ -8,7 +8,8 @@ pub enum DvmValue {
|
||||
Long(i64),
|
||||
Double(f64),
|
||||
Boolean(bool),
|
||||
Pointer(Rc<DmAllocObject>),
|
||||
Object(Rc<DmAllocObject>),
|
||||
USize(usize),
|
||||
Uninit,
|
||||
Void,
|
||||
}
|
||||
@ -18,15 +19,23 @@ impl DvmValue {
|
||||
if let DvmValue::Long(l) = self {
|
||||
*l
|
||||
} else {
|
||||
panic!("Expected DvmValue::Long, but found {:?}", self)
|
||||
panic!("Expected DvmValue::Long, but found DvmValue::{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_pointer(&self) -> Rc<DmAllocObject> {
|
||||
if let DvmValue::Pointer(p) = self {
|
||||
p.clone()
|
||||
pub fn expect_object(&self) -> Rc<DmAllocObject> {
|
||||
if let DvmValue::Object(o) = self {
|
||||
o.clone()
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
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::symbol::LibSymbol;
|
||||
use crate::vm::lib::DmLib;
|
||||
|
||||
pub fn load_module(bytes: &[u8]) -> Result<DmLib, String> {
|
||||
let mut ip: usize = 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::vm::lib::DmLib;
|
||||
use crate::vm::lib::magic::{COMPILER_VERSION_STRING, DEIMOS_MAGIC_STRING};
|
||||
use crate::vm::lib::DmLib;
|
||||
|
||||
macro_rules! push_byte_array {
|
||||
( $dest: expr, $arr: expr ) => {
|
||||
|
@ -1,40 +1,9 @@
|
||||
use crate::vm::dm_type::DmType;
|
||||
use crate::vm::dvm_value::DvmValue;
|
||||
use crate::vm::object_type::{DmField, DmImplementation};
|
||||
use std::alloc::{alloc, dealloc, Layout};
|
||||
use std::collections::HashSet;
|
||||
use crate::vm::object::DmAllocObject;
|
||||
use crate::vm::object_type::DmField;
|
||||
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 {
|
||||
let data_size = dm_field.dm_type().size_in_bytes();
|
||||
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(),
|
||||
)),
|
||||
DmType::Boolean => DvmValue::Boolean(raw_data[0] != 0),
|
||||
DmType::Pointer => {
|
||||
DmType::Object => {
|
||||
// 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))
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
247
src/vm/mod.rs
247
src/vm/mod.rs
@ -2,14 +2,16 @@ pub mod dm_type;
|
||||
pub mod dvm_value;
|
||||
pub mod lib;
|
||||
pub mod mem;
|
||||
mod object;
|
||||
pub mod object_type;
|
||||
pub mod op_codes;
|
||||
pub mod platform;
|
||||
mod pointer;
|
||||
pub mod util;
|
||||
|
||||
use crate::vm::dvm_value::DvmValue;
|
||||
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 op_codes::*;
|
||||
use std::alloc::{alloc, dealloc, Layout};
|
||||
@ -19,13 +21,15 @@ use std::rc::Rc;
|
||||
pub type PlatformFunction =
|
||||
fn(args: Vec<DvmValue>, state: &mut DvmState, context: &DvmContext) -> DvmValue;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum CallFrame {
|
||||
PlatformCall(CallFrameInfo),
|
||||
DeimosCall(CallFrameInfo),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CallFrameInfo {
|
||||
fn_fqn: String,
|
||||
pub fqn: String,
|
||||
}
|
||||
|
||||
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 {
|
||||
self.libs.push(lib.clone());
|
||||
for lib_fn in &lib.functions {
|
||||
@ -75,14 +79,19 @@ impl DvmContext {
|
||||
.iter()
|
||||
.flat_map(|implementation| &implementation.methods)
|
||||
{
|
||||
self.functions.insert(
|
||||
method.dm_fn().fqn().to_string(),
|
||||
method.dm_fn().clone(),
|
||||
);
|
||||
self.functions
|
||||
.insert(method.dm_fn().fqn().to_string(), 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>> {
|
||||
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(
|
||||
state: &mut DvmState,
|
||||
context: &DvmContext,
|
||||
@ -116,7 +149,7 @@ pub fn call_fn(
|
||||
) -> DvmValue {
|
||||
// save current state
|
||||
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());
|
||||
|
||||
@ -129,8 +162,8 @@ pub fn call_fn(
|
||||
}
|
||||
|
||||
// push args
|
||||
for arg in args {
|
||||
state.registers.push(arg);
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
state.registers[i] = arg.clone();
|
||||
}
|
||||
|
||||
// run the byte code
|
||||
@ -233,31 +266,23 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
|
||||
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));
|
||||
state.registers[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));
|
||||
state.registers[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));
|
||||
state.registers[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())
|
||||
state.registers[target_register] = source_value.clone();
|
||||
}
|
||||
ALLOC => {
|
||||
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));
|
||||
|
||||
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);
|
||||
state.registers[target_register] = DvmValue::Object(Rc::new(dm_alloc_object));
|
||||
}
|
||||
DEALLOC => {
|
||||
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
|
||||
state.registers[target_register] = DvmValue::Uninit;
|
||||
}
|
||||
MOV_INT_TO => {
|
||||
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
|
||||
.get(target_register)
|
||||
.unwrap()
|
||||
.expect_pointer();
|
||||
.expect_object();
|
||||
write_bytes!(dm_alloc_object.data, offset, operand.to_ne_bytes());
|
||||
}
|
||||
MOV_LONG_TO => {
|
||||
@ -312,7 +341,7 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
|
||||
.registers
|
||||
.get(target_register)
|
||||
.unwrap()
|
||||
.expect_pointer();
|
||||
.expect_object();
|
||||
|
||||
let source_value = state.registers.get(source_register).unwrap();
|
||||
match source_value {
|
||||
@ -331,14 +360,17 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
|
||||
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());
|
||||
DvmValue::Object(source_object) => {
|
||||
let source_object_ptr = Rc::into_raw(source_object.clone());
|
||||
write_bytes!(
|
||||
target_alloc_object.data,
|
||||
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 => {
|
||||
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 => {
|
||||
// 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 address_register = next_8!(iter, usize);
|
||||
let size_register = next_8!(iter, usize);
|
||||
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);
|
||||
let const_id = next_32_le!(iter, usize);
|
||||
|
||||
// Get constant
|
||||
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 DmConstant::String(s) = constant;
|
||||
|
||||
// Get allocated PointerImpl
|
||||
let pointer_impl = state
|
||||
.registers
|
||||
.get(pointer_impl_register)
|
||||
.unwrap()
|
||||
.expect_pointer();
|
||||
// Alloc memory for constant
|
||||
let size = s.len();
|
||||
let layout = Layout::from_size_align(size, 1).unwrap();
|
||||
let raw_pointer = unsafe { alloc(layout) };
|
||||
|
||||
// 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,
|
||||
)
|
||||
// Move constant to memory
|
||||
let bytes = s.as_bytes();
|
||||
for i in 0..size {
|
||||
unsafe {
|
||||
raw_pointer.add(i).write(bytes[i]);
|
||||
}
|
||||
}
|
||||
.expect_long() as usize as *mut u8;
|
||||
|
||||
// Write the constant bytes to the raw_ptr
|
||||
write_string!(raw_ptr, s);
|
||||
|
||||
// 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()),
|
||||
],
|
||||
);
|
||||
// Store the pointer metadata in target registers.
|
||||
state.registers[address_register] = DvmValue::USize(raw_pointer as usize);
|
||||
state.registers[size_register] = DvmValue::USize(size);
|
||||
}
|
||||
ALLOC_RAW => {
|
||||
// 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
|
||||
// DvmValue::Long.
|
||||
let target_register = next_8!(iter, usize);
|
||||
// of the source register.
|
||||
let address_register = next_8!(iter, usize);
|
||||
let source_register = next_8!(iter, usize);
|
||||
let number_of_bytes =
|
||||
state.registers.get(source_register).unwrap().expect_long() as usize;
|
||||
let layout = Layout::from_size_align(number_of_bytes, 0).unwrap();
|
||||
let ptr = unsafe { alloc(layout) };
|
||||
state
|
||||
.registers
|
||||
.insert(target_register, DvmValue::Long(ptr as i64))
|
||||
let size = state.registers.get(source_register).unwrap().expect_long() as usize;
|
||||
let layout = Layout::from_size_align(size, 1).unwrap();
|
||||
let raw_ptr = unsafe { alloc(layout) };
|
||||
state.registers[address_register] = DvmValue::USize(raw_ptr as usize);
|
||||
}
|
||||
DEALLOC_RAW => {
|
||||
// Deallocates a raw number of bytes at an address, with the number of bytes
|
||||
// determined by the value in the source register, and the address stored in the
|
||||
// target register.
|
||||
let target_register = next_8!(iter, usize);
|
||||
let source_register = next_8!(iter, usize);
|
||||
let number_of_bytes =
|
||||
state.registers.get(source_register).unwrap().expect_long() as usize;
|
||||
|
||||
let layout = Layout::from_size_align(number_of_bytes, 0).unwrap();
|
||||
let ptr =
|
||||
state.registers.get(target_register).unwrap().expect_long() as usize as *mut u8;
|
||||
// Deallocates a DvmValue::Pointer(DvmPointer) in the target register.
|
||||
let address_register = next_8!(iter, usize);
|
||||
let size_register = next_8!(iter, usize);
|
||||
let address = state
|
||||
.registers
|
||||
.get(address_register)
|
||||
.unwrap()
|
||||
.expect_usize();
|
||||
let size = state.registers.get(size_register).unwrap().expect_usize();
|
||||
let layout = Layout::from_size_align(size, 1).unwrap();
|
||||
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 => {
|
||||
// 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();
|
||||
state
|
||||
.call_stack
|
||||
.push(CallFrame::PlatformCall(CallFrameInfo {
|
||||
fn_fqn: symbol_name,
|
||||
}));
|
||||
.push(CallFrame::PlatformCall(CallFrameInfo { fqn: symbol_name }));
|
||||
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();
|
||||
}
|
||||
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 call_result = call_fn(state, context, dm_fn, args);
|
||||
state.registers.insert(return_register, call_result);
|
||||
state.registers[return_register] = call_result;
|
||||
}
|
||||
INVOKE_VIRTUAL => {
|
||||
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());
|
||||
}
|
||||
|
||||
let self_obj = args.get(0).unwrap().expect_pointer();
|
||||
let self_obj = args.get(0).unwrap().expect_object();
|
||||
let method = self_obj
|
||||
.implementation
|
||||
.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 call_result = call_fn(state, context, &dm_fn, args);
|
||||
state.registers.insert(return_register, call_result);
|
||||
state.registers[return_register] = call_result;
|
||||
}
|
||||
INVOKE_DYNAMIC => {
|
||||
unimplemented!("INVOKE_DYNAMIC is not yet supported and may never be.")
|
||||
|
34
src/vm/object.rs
Normal file
34
src/vm/object.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
use crate::vm::dm_type::DmType;
|
||||
use crate::vm::mem::DmAllocObject;
|
||||
use crate::vm::object::DmAllocObject;
|
||||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
@ -75,9 +75,9 @@ pub fn add_mov_register(code: &mut Vec<u8>, target_register: u8, 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(register);
|
||||
code.push(target_register);
|
||||
push_number!(code, size);
|
||||
push_number!(code, implementation_name.len() as u32);
|
||||
push_string!(code, implementation_name);
|
||||
@ -113,9 +113,16 @@ pub fn add_mov_register_to(
|
||||
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(register);
|
||||
code.push(address_register);
|
||||
code.push(size_register);
|
||||
push_number!(code, lib_name.len() as u32);
|
||||
push_string!(code, lib_name);
|
||||
push_number!(code, const_id);
|
||||
@ -125,14 +132,13 @@ pub fn add_platform_call(
|
||||
code: &mut Vec<u8>,
|
||||
symbol_name: &str,
|
||||
return_register: u8,
|
||||
arg_registers_length: u8,
|
||||
arg_registers: &Vec<u8>,
|
||||
arg_registers: &[u8],
|
||||
) {
|
||||
code.push(PLATFORM_CALL);
|
||||
push_number!(code, symbol_name.len() as u32);
|
||||
push_string!(code, symbol_name);
|
||||
push_number!(code, return_register);
|
||||
push_number!(code, arg_registers_length);
|
||||
push_number!(code, arg_registers.len() as u8);
|
||||
for &b in arg_registers {
|
||||
code.push(b);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
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 std::rc::Rc;
|
||||
|
||||
@ -30,14 +31,15 @@ unsafe fn get_string(dvm_value: &DvmValue) -> String {
|
||||
DvmValue::Long(l) => l.to_string(),
|
||||
DvmValue::Double(d) => d.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::Void => String::from("Void"),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_to_string(alloc_object_rc: Rc<DmAllocObject>) -> String {
|
||||
if alloc_object_rc.implementation.fqn == "std::core::String" {
|
||||
fn object_to_string(alloc_object_rc: Rc<DmAllocObject>) -> String {
|
||||
if alloc_object_rc.implementation.fqn == "std::core::StringImpl" {
|
||||
extract_string_from_string(alloc_object_rc.clone())
|
||||
} else {
|
||||
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
|
||||
.get_field("bytes", &string_object)
|
||||
.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" {
|
||||
panic!("String.bytes field is not a std::core::ArrayImpl");
|
||||
}
|
||||
|
||||
let pointer_field = bytes_object
|
||||
let ptr_address_field = bytes_object
|
||||
.implementation
|
||||
.get_field("pointer", &bytes_object)
|
||||
.expect("Could not get ArrayImpl.pointer field.");
|
||||
let pointer_object = unsafe { get_field_value(&pointer_field, &bytes_object) }.expect_pointer();
|
||||
if pointer_object.implementation.fqn != "std::unsafe::PointerImpl" {
|
||||
panic!("ArrayImpl.pointer is not a std::unsafe::PointerImpl");
|
||||
}
|
||||
.get_field("ptr_address", &bytes_object)
|
||||
.expect("Could not get ArrayImpl.ptr_address field.");
|
||||
let address = unsafe { get_field_value(&ptr_address_field, &bytes_object) }.expect_usize();
|
||||
|
||||
let raw_address_field = pointer_object
|
||||
let ptr_size_field = bytes_object
|
||||
.implementation
|
||||
.get_field("raw_address", &pointer_object)
|
||||
.expect("Could not get PointerImpl.raw_address field.");
|
||||
let raw_address = unsafe { get_field_value(&raw_address_field, &pointer_object) }.expect_long();
|
||||
.get_field("ptr_size", &bytes_object)
|
||||
.expect("Could not get ArrayImpl.ptr_size field.");
|
||||
let size = unsafe { get_field_value(&ptr_size_field, &bytes_object) }.expect_usize();
|
||||
|
||||
let size_field = pointer_object
|
||||
.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 raw_bytes_pointer = address as *mut u8;
|
||||
let mut v: Vec<u8> = Vec::new();
|
||||
for i in 0..(size as isize) {
|
||||
v.push(unsafe { raw_bytes_pointer.offset(i).read() });
|
||||
for i in 0..size {
|
||||
v.push(unsafe { raw_bytes_pointer.add(i).read() });
|
||||
}
|
||||
String::from_utf8(v).unwrap()
|
||||
}
|
||||
|
27
src/vm/pointer.rs
Normal file
27
src/vm/pointer.rs
Normal 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))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user