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),
+                )
+            }
+        }
+    }
+}