riscv_etrace/types/
stack.rs1pub trait ReturnStack: Sized {
9 fn new(max_depth: usize) -> Option<Self>;
15
16 fn push(&mut self, addr: u64);
21
22 fn pop(&mut self) -> Option<u64>;
24
25 fn depth(&self) -> usize;
27
28 fn max_depth(&self) -> usize;
30}
31
32#[derive(Clone, Debug)]
37pub struct StaticStack<const N: usize> {
38 data: [u64; N],
39 max_depth: usize,
40 depth: usize,
41 base: usize,
42}
43
44impl<const N: usize> ReturnStack for StaticStack<N> {
45 fn new(max_depth: usize) -> Option<Self> {
46 if max_depth > N {
47 None
48 } else {
49 Some(Self {
50 data: [0; N],
51 max_depth,
52 depth: 0,
53 base: 0,
54 })
55 }
56 }
57
58 fn push(&mut self, addr: u64) {
59 let depth = self.depth;
60 self.data[(self.base + depth) % N] = addr;
61
62 if depth < self.max_depth {
63 self.depth = depth.saturating_add(1);
64 } else {
65 let base = self.base + 1;
66 if base < N {
67 self.base = base;
68 } else {
69 self.base = 0;
70 }
71 }
72 }
73
74 fn pop(&mut self) -> Option<u64> {
75 let depth = self.depth.checked_sub(1)?;
76 self.depth = depth;
77 Some(self.data[(self.base + depth) % N])
78 }
79
80 fn depth(&self) -> usize {
81 self.depth
82 }
83
84 fn max_depth(&self) -> usize {
85 self.max_depth
86 }
87}
88
89pub struct NoStack;
94
95impl ReturnStack for NoStack {
96 fn new(max_depth: usize) -> Option<Self> {
97 (max_depth == 0).then_some(Self)
98 }
99
100 fn push(&mut self, _: u64) {}
101
102 fn pop(&mut self) -> Option<u64> {
103 None
104 }
105
106 fn depth(&self) -> usize {
107 0
108 }
109
110 fn max_depth(&self) -> usize {
111 0
112 }
113}
114
115#[cfg(feature = "alloc")]
116use alloc::collections::VecDeque;
117#[derive(Clone, Debug)]
118#[cfg(feature = "alloc")]
119pub struct VecStack {
120 data: VecDeque<u64>,
121 max_depth: usize,
122}
123
124#[cfg(feature = "alloc")]
125impl ReturnStack for VecStack {
126 fn new(max_size: usize) -> Option<Self> {
127 Some(Self {
128 data: VecDeque::with_capacity(max_size),
129 max_depth: max_size,
130 })
131 }
132
133 fn depth(&self) -> usize {
134 self.data.len()
135 }
136
137 fn push(&mut self, addr: u64) {
139 self.push_back(addr);
140 }
141 fn pop(&mut self) -> Option<u64> {
142 self.pop_back()
143 }
144 fn max_depth(&self) -> usize {
145 self.max_depth
146 }
147}
148
149#[cfg(feature = "alloc")]
150impl VecStack {
151 pub fn push_back(&mut self, addr: u64) {
153 if self.max_depth == 0 {
154 return;
155 }
156 if self.data.len() == self.max_depth {
157 self.data.pop_front();
158 }
159 self.data.push_back(addr);
160 }
161
162 pub fn push_front(&mut self, addr: u64) {
164 if self.max_depth == 0 {
165 return;
166 }
167 if self.data.len() == self.max_depth {
168 self.data.pop_back();
169 }
170 self.data.push_front(addr);
171 }
172
173 pub fn pop_back(&mut self) -> Option<u64> {
175 self.data.pop_back()
176 }
177
178 pub fn pop_front(&mut self) -> Option<u64> {
180 self.data.pop_front()
181 }
182}
183
184#[cfg(feature = "alloc")]
185use alloc::{boxed::Box, vec};
186#[derive(Clone, Debug)]
187#[cfg(feature = "alloc")]
188pub struct BoxStack {
189 data: Box<[u64]>,
190 depth: usize,
191 base: usize,
192}
193
194#[cfg(feature = "alloc")]
195impl ReturnStack for BoxStack {
196 fn new(max_depth: usize) -> Option<Self> {
197 if max_depth == 0 {
198 return None;
199 }
200 Some(Self {
201 data: vec![0u64; max_depth].into_boxed_slice(),
202 depth: 0,
203 base: 0,
204 })
205 }
206
207 fn push(&mut self, addr: u64) {
208 let max_len = self.data.len();
209 let index = (self.depth + self.base) % max_len;
210 self.data[index] = addr;
211
212 if self.depth < max_len {
213 self.depth += 1;
214 } else {
215 self.base = (self.base + 1) % max_len;
216 }
217 }
218
219 fn pop(&mut self) -> Option<u64> {
220 let depth = self.depth.checked_sub(1)?;
221 self.depth = depth;
222 Some(self.data[(self.base + depth) % self.data.len()])
223 }
224
225 fn depth(&self) -> usize {
226 self.depth
227 }
228
229 fn max_depth(&self) -> usize {
230 self.data.len()
231 }
232}