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 */
5
6use swamp_vm_types::{
7    ConstantMemoryAddress, FrameMemoryAddress, MemoryAlignment, MemorySize, align_frame_addr,
8};
9use tracing::error;
10
11const ALIGNMENT: u16 = 8;
12const ALIGNMENT_REST: u16 = ALIGNMENT - 1;
13const ALIGNMENT_MASK: u16 = !ALIGNMENT_REST;
14
15#[derive(Debug, Copy, Clone)]
16pub struct ConstantMemoryRegion {
17    pub addr: ConstantMemoryAddress,
18    pub size: MemorySize,
19}
20
21#[derive(Debug, Copy, Clone)]
22pub struct FrameMemoryRegion {
23    pub addr: FrameMemoryAddress,
24    pub size: MemorySize,
25}
26
27impl Default for FrameMemoryRegion {
28    fn default() -> Self {
29        Self {
30            addr: FrameMemoryAddress(0),
31            size: MemorySize(0),
32        }
33    }
34}
35
36impl FrameMemoryRegion {
37    pub(crate) fn new(frame_addr: FrameMemoryAddress, size: MemorySize) -> FrameMemoryRegion {
38        Self {
39            addr: frame_addr,
40            size,
41        }
42    }
43
44    pub fn last_valid_end_addr(&self) -> FrameMemoryAddress {
45        self.addr.add(MemorySize(self.size.0))
46    }
47}
48
49impl FrameMemoryRegion {
50    #[must_use]
51    pub fn addr(&self) -> FrameMemoryAddress {
52        self.addr
53    }
54}
55
56#[derive(Copy, Clone)]
57pub struct ScopeAllocator {
58    initial_addr: FrameMemoryAddress,
59    addr: FrameMemoryAddress,
60    target_info: FrameMemoryRegion,
61}
62
63impl ScopeAllocator {
64    #[must_use]
65    pub const fn new(target_info: FrameMemoryRegion) -> Self {
66        Self {
67            initial_addr: target_info.addr,
68            addr: target_info.addr,
69            target_info,
70        }
71    }
72
73    pub fn allocate(&mut self, size: MemorySize, alignment: MemoryAlignment) -> FrameMemoryAddress {
74        let start_addr = align_frame_addr(self.addr, alignment);
75
76        self.addr = start_addr.add(size);
77
78        if self.addr.0 > self.target_info.last_valid_end_addr().0 {
79            error!("out of alloc memory");
80        }
81
82        assert!(self.addr.0 <= self.target_info.last_valid_end_addr().0);
83
84        start_addr
85    }
86
87    pub fn reserve(&mut self, size: MemorySize, alignment: MemoryAlignment) -> FrameMemoryRegion {
88        FrameMemoryRegion {
89            addr: self.allocate(size, alignment),
90            size,
91        }
92    }
93
94    #[must_use]
95    pub const fn create_scope(&self) -> Self {
96        Self {
97            addr: self.addr,
98            initial_addr: self.addr,
99            target_info: self.target_info,
100        }
101    }
102
103    #[must_use]
104    pub const fn addr(&self) -> FrameMemoryAddress {
105        self.addr
106    }
107
108    pub fn reset(&mut self) {
109        self.addr = self.initial_addr;
110    }
111}