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