swamp_script_code_gen/
constants.rs

1use swamp_vm_types::{MemoryAddress, MemoryAlignment, MemorySize};
2
3const CONSTANTS_START: u16 = 0xFFFF;
4const ALIGNMENT_MASK: usize = 0x7;
5
6pub struct ConstantsAllocator {
7    current_addr: MemoryAddress,
8}
9
10impl Default for ConstantsAllocator {
11    fn default() -> Self {
12        Self::new()
13    }
14}
15
16impl ConstantsAllocator {
17    #[must_use]
18    pub const fn new() -> Self {
19        Self {
20            current_addr: MemoryAddress(CONSTANTS_START),
21        }
22    }
23
24    pub fn allocate(&mut self, size: MemorySize, alignment_enum: MemoryAlignment) -> MemoryAddress {
25        let alignment: usize = alignment_enum.into();
26
27        let aligned_size = (size.0 as usize + alignment - 1) & !(alignment - 1);
28
29        self.current_addr =
30            MemoryAddress((self.current_addr.0 - aligned_size as u16) & !(alignment - 1) as u16);
31
32        self.current_addr
33    }
34
35    pub fn reset(&mut self) {
36        self.current_addr = MemoryAddress(CONSTANTS_START);
37    }
38}
39
40pub struct ConstantsManager {
41    allocator: ConstantsAllocator,
42    data: Vec<u8>,
43}
44
45impl Default for ConstantsManager {
46    fn default() -> Self {
47        Self::new()
48    }
49}
50
51impl ConstantsManager {
52    #[must_use]
53    pub const fn new() -> Self {
54        Self {
55            allocator: ConstantsAllocator::new(),
56            data: Vec::new(),
57        }
58    }
59
60    pub fn allocate(&mut self, data: &[u8], alignment_enum: MemoryAlignment) -> MemoryAddress {
61        let addr = self
62            .allocator
63            .allocate(MemorySize(data.len() as u16), alignment_enum);
64
65        let required_len = (CONSTANTS_START - addr.0 + 1) as usize;
66        if required_len > self.data.len() {
67            self.data.resize(required_len, 0);
68        }
69
70        let start_idx = (CONSTANTS_START - addr.0 - data.len() as u16) as usize;
71        self.data[start_idx..start_idx + data.len()].copy_from_slice(data);
72
73        addr
74    }
75
76    pub fn take_data(self) -> Vec<u8> {
77        self.data
78    }
79}