swamp_code_gen/
constants.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use swamp_types::TypeRef;
6use swamp_vm_isa::aligner::{align, SAFE_ALIGNMENT};
7use swamp_vm_isa::HeapMemoryAddress;
8use swamp_vm_layout::LayoutCache;
9use swamp_vm_types::types::{HeapPlacedArray, HeapPlacedType};
10
11pub struct ConstantsAllocator {
12    current_addr: u32,
13    max_size: u32,
14}
15
16impl ConstantsAllocator {
17    #[must_use]
18    pub const fn new(max_size: u32) -> Self {
19        Self {
20            current_addr: SAFE_ALIGNMENT as u32, // Reserve space (alignment distance) so no valid heap address is zero
21            max_size,
22        }
23    }
24
25    /// # Panics
26    ///
27    pub fn allocate(&mut self, layout_cache: &mut LayoutCache, ty: &TypeRef) -> HeapPlacedType {
28        let gen_type = layout_cache.layout(ty);
29        let alignment: usize = gen_type.max_alignment.into();
30        let start_addr = align(self.current_addr as usize, alignment) as u32;
31
32        self.current_addr = start_addr + gen_type.total_size.0;
33        assert!(self.current_addr < self.max_size);
34
35        HeapPlacedType::new(HeapMemoryAddress(start_addr), gen_type)
36    }
37
38    /// # Panics
39    ///
40    pub fn allocate_byte_array(&mut self, byte_count: u32) -> HeapPlacedArray {
41        let start_addr = align(self.current_addr as usize, SAFE_ALIGNMENT) as u32;
42        self.current_addr = start_addr + byte_count;
43        assert!(self.current_addr < self.max_size);
44
45        HeapPlacedArray::new(HeapMemoryAddress(start_addr), byte_count)
46    }
47
48    pub const fn reset(&mut self) {
49        self.current_addr = SAFE_ALIGNMENT as u32;
50    }
51}
52
53pub struct ConstantsManager {
54    pub(crate) allocator: ConstantsAllocator,
55    data: Vec<u8>,
56}
57
58impl ConstantsManager {
59    #[must_use]
60    pub fn new(memory_size: u32) -> Self {
61        let data = vec![0; memory_size as usize];
62        Self {
63            allocator: ConstantsAllocator::new(memory_size),
64            data,
65        }
66    }
67
68    pub fn allocate_byte_array(&mut self, data: &[u8]) -> HeapPlacedArray {
69        let count = data.len();
70        if count == 0 {
71            return HeapPlacedArray::new(HeapMemoryAddress(0), 0);
72        }
73        let addr = self.allocator.allocate_byte_array(count as u32);
74        let start_idx = addr.addr().0 as usize;
75        self.data[start_idx..start_idx + data.len()].copy_from_slice(data);
76
77        addr
78    }
79
80    #[must_use]
81    pub fn take_data(self) -> Vec<u8> {
82        let safe_size = align(self.allocator.current_addr as usize, SAFE_ALIGNMENT);
83        self.data[..safe_size].to_vec()
84    }
85}