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