1use 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}