swamp_code_gen/
alloc.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::{MemoryAlignment, MemorySize};
7use swamp_vm_layout::LayoutCache;
8use swamp_vm_types::types::{BasicTypeRef, FramePlacedType};
9use swamp_vm_types::{align_frame_addr, FrameMemoryAddress, FrameMemoryRegion};
10use tracing::error;
11
12#[derive(Copy, Clone, Debug)]
13pub struct StackFrameAllocator {
14    initial_addr: FrameMemoryAddress,
15    addr: FrameMemoryAddress,
16    target_info: FrameMemoryRegion,
17}
18
19impl StackFrameAllocator {
20    #[must_use]
21    pub const fn new(target_info: FrameMemoryRegion) -> Self {
22        Self {
23            initial_addr: target_info.addr,
24            addr: target_info.addr,
25            target_info,
26        }
27    }
28
29    pub fn allocate(&mut self, size: MemorySize, alignment: MemoryAlignment) -> FrameMemoryAddress {
30        let start_addr = align_frame_addr(self.addr, alignment);
31
32        self.addr = start_addr.add(size);
33
34        if self.addr.0 > self.target_info.last_valid_end_addr().0 {
35            error!(
36                "out of alloc memory {}",
37                self.target_info.last_valid_end_addr()
38            );
39        }
40
41        assert!(self.addr.0 <= self.target_info.last_valid_end_addr().0);
42
43        start_addr
44    }
45
46    pub fn allocate_type(&mut self, gen_type: &BasicTypeRef) -> FramePlacedType {
47        FramePlacedType::new(
48            self.allocate(gen_type.total_size, gen_type.max_alignment),
49            gen_type.clone(),
50        )
51    }
52
53    pub fn reserve(
54        &mut self,
55        layout_cache: &mut LayoutCache,
56        analyzed_type: &TypeRef,
57    ) -> FramePlacedType {
58        let gen_type = layout_cache.layout(analyzed_type);
59        self.allocate_type(&gen_type)
60    }
61
62    #[must_use]
63    pub const fn create_scope(&self) -> Self {
64        Self {
65            addr: self.addr,
66            initial_addr: self.addr,
67            target_info: self.target_info,
68        }
69    }
70
71    #[must_use]
72    pub const fn addr(&self) -> FrameMemoryAddress {
73        self.addr
74    }
75
76    pub const fn reset(&mut self) {
77        self.addr = self.initial_addr;
78    }
79}