nova_interpreter/
primitives.rs

1use std::alloc::{self, Layout};
2
3use vera_prim_macro::prim;
4
5use crate as nova_interpreter;
6use crate::utils::PrimitiveFn;
7
8use crate::utils::interner::Interner;
9
10/// A wrapper for a `Vec` of builtins so that functions
11/// can be added to it
12pub struct Builtins<'a> {
13    pub builtins: &'a mut Vec<(Box<[usize]>, PrimitiveFn)>,
14}
15
16impl<'a> Builtins<'a> {
17    pub fn new(builtins: &'a mut Vec<(Box<[usize]>, PrimitiveFn)>) -> Self {
18        Builtins { builtins }
19    }
20
21    pub fn add_builtin(&mut self, conditions: Vec<usize>, prim: PrimitiveFn) {
22        self.builtins.push((conditions.into_boxed_slice(), prim))
23    }
24}
25
26/// Add the memory manipulation builtins to the passed in builtins object
27pub fn add_memory_manipulation_builtins(interner: &mut Interner<String>, builtins: &mut Builtins) {
28    prim!(
29        mem_alloc,
30        |mem_bytes| {
31            let bytes = mem_bytes;
32            let layout_size = size_of::<Layout>();
33
34            let layout = Layout::from_size_align(bytes + layout_size, 8).unwrap();
35            let mem = unsafe { alloc::alloc(layout) };
36
37            unsafe { *(mem as *mut Layout) = layout };
38
39            (mem as usize + layout_size,)
40        },
41        (mem_pointer,)
42    );
43
44    prim!(
45        mem_write,
46        |mem_value, mem_pointer| {
47            unsafe { *(mem_pointer as *mut u8) = mem_value as u8 };
48        },
49        ()
50    );
51
52    prim!(
53        mem_read,
54        |mem_pointer| { (unsafe { *(mem_pointer as *mut u8) as usize },) },
55        (mem_value,)
56    );
57
58    prim!(
59        mem_copy,
60        |mem_src, mem_dest, mem_bytes| unsafe {
61            std::ptr::copy_nonoverlapping(mem_src as *mut u8, mem_dest as *mut u8, mem_bytes)
62        },
63        ()
64    );
65
66    prim!(
67        mem_free,
68        |mem_pointer| {
69            let layout_size = size_of::<Layout>();
70
71            let ptr = (mem_pointer - layout_size) as *mut u8;
72            let layout = unsafe { *(ptr as *mut Layout) };
73            unsafe { alloc::dealloc(ptr, layout) }
74        },
75        ()
76    );
77}