swamp_script_code_gen/
constants.rs1use 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}