diff --git a/Cargo.lock b/Cargo.lock index 7b70c0b028a2ebcd5ca1f99ac68b192fbec83b98..088dc069576e8c566b9f4d946dcf8ac61413f36a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -651,6 +651,10 @@ dependencies = [ "take_mut", ] +[[package]] +name = "hercules_rt" +version = "0.1.0" + [[package]] name = "hermit-abi" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index dc0c64789c6ce2abdc8ec53757c05f64010738bf..86307fd85b5fc707ce4bd9db7f645d5fea8c5dbb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "hercules_cg", "hercules_ir", "hercules_opt", + "hercules_rt", "hercules_tools/hercules_driver", diff --git a/hercules_rt/Cargo.toml b/hercules_rt/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..0bf19adf352512e3bd5639015e62c38e13670f85 --- /dev/null +++ b/hercules_rt/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "hercules_rt" +version = "0.1.0" +authors = ["Russel Arbore <rarbore2@illinois.edu>"] + +[dependencies] + diff --git a/hercules_rt/src/lib.rs b/hercules_rt/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..bb460ab51ed9b5b8b76478e52f7007d2e4eb51a7 --- /dev/null +++ b/hercules_rt/src/lib.rs @@ -0,0 +1,91 @@ +use std::alloc::{alloc, alloc_zeroed, dealloc, Layout}; +use std::marker::PhantomData; +use std::ptr::{copy_nonoverlapping, NonNull}; + +/* + * An in-memory collection object that can be used by functions compiled by the + * Hercules compiler. + */ +pub struct HerculesBox<'a> { + cpu_shared: Option<NonNull<u8>>, + cpu_exclusive: Option<NonNull<u8>>, + cpu_owned: Option<NonNull<u8>>, + + size: usize, + _phantom: PhantomData<&'a u8>, +} + +impl<'a> HerculesBox<'a> { + pub fn from_slice<T>(slice: &'a [T]) -> Self { + HerculesBox { + cpu_shared: Some(unsafe { NonNull::new_unchecked(slice.as_ptr() as *mut u8) }), + cpu_exclusive: None, + cpu_owned: None, + size: slice.len() * align_of::<T>(), + _phantom: PhantomData, + } + } + + pub fn from_slice_mut<T>(slice: &'a mut [T]) -> Self { + HerculesBox { + cpu_shared: None, + cpu_exclusive: Some(unsafe { NonNull::new_unchecked(slice.as_mut_ptr() as *mut u8) }), + cpu_owned: None, + size: slice.len() * align_of::<T>(), + _phantom: PhantomData, + } + } + + unsafe fn into_cpu(&mut self) -> NonNull<u8> { + self.cpu_shared + .or(self.cpu_exclusive) + .or(self.cpu_owned) + .unwrap() + } + + unsafe fn into_cpu_mut(&mut self) -> NonNull<u8> { + if let Some(ptr) = self.cpu_exclusive.or(self.cpu_owned) { + ptr + } else { + let ptr = + NonNull::new(alloc(Layout::from_size_align_unchecked(self.size, 16))).unwrap(); + copy_nonoverlapping(self.cpu_shared.unwrap().as_ptr(), ptr.as_ptr(), self.size); + self.cpu_owned = Some(ptr); + self.cpu_shared = None; + ptr + } + } + + pub unsafe fn __zeros(size: usize) -> Self { + HerculesBox { + cpu_shared: None, + cpu_exclusive: None, + cpu_owned: Some( + NonNull::new(alloc_zeroed(Layout::from_size_align_unchecked(size, 16))).unwrap(), + ), + size: size, + _phantom: PhantomData, + } + } + + pub unsafe fn __cpu_ptr(&mut self) -> *mut u8 { + self.into_cpu().as_ptr() + } + + pub unsafe fn __cpu_ptr_mut(&mut self) -> *mut u8 { + self.into_cpu_mut().as_ptr() + } +} + +impl<'a> Drop for HerculesBox<'a> { + fn drop(&mut self) { + if let Some(ptr) = self.cpu_owned { + unsafe { + dealloc( + ptr.as_ptr(), + Layout::from_size_align_unchecked(self.size, 16), + ) + } + } + } +}