| 1 | use std::collections::HashMap; |
| 2 | |
| 3 | use crate::resolve::SymbolId; |
| 4 | |
| 5 | pub const THREAD_POINTER_SIZE: u32 = 8; |
| 6 | pub const THREAD_VARIABLE_DESCRIPTOR_SIZE: u32 = 24; |
| 7 | |
| 8 | #[derive(Debug, Clone, PartialEq, Eq, Default)] |
| 9 | pub struct ThreadPointerSection { |
| 10 | pub entries: Vec<ThreadPointerEntry>, |
| 11 | pub index: HashMap<SymbolId, usize>, |
| 12 | } |
| 13 | |
| 14 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 15 | pub struct ThreadPointerEntry { |
| 16 | pub symbol: SymbolId, |
| 17 | } |
| 18 | |
| 19 | impl ThreadPointerSection { |
| 20 | pub fn intern(&mut self, symbol: SymbolId) -> usize { |
| 21 | if let Some(&idx) = self.index.get(&symbol) { |
| 22 | return idx; |
| 23 | } |
| 24 | let idx = self.entries.len(); |
| 25 | self.entries.push(ThreadPointerEntry { symbol }); |
| 26 | self.index.insert(symbol, idx); |
| 27 | idx |
| 28 | } |
| 29 | |
| 30 | pub fn get(&self, symbol: SymbolId) -> Option<(usize, &ThreadPointerEntry)> { |
| 31 | let idx = *self.index.get(&symbol)?; |
| 32 | Some((idx, &self.entries[idx])) |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | #[cfg(test)] |
| 37 | mod tests { |
| 38 | use super::*; |
| 39 | |
| 40 | #[test] |
| 41 | fn intern_deduplicates_thread_pointer_slots() { |
| 42 | let mut ptrs = ThreadPointerSection::default(); |
| 43 | let a = ptrs.intern(SymbolId(5)); |
| 44 | let b = ptrs.intern(SymbolId(5)); |
| 45 | let c = ptrs.intern(SymbolId(9)); |
| 46 | assert_eq!(a, 0); |
| 47 | assert_eq!(b, 0); |
| 48 | assert_eq!(c, 1); |
| 49 | assert_eq!(ptrs.entries.len(), 2); |
| 50 | } |
| 51 | } |
| 52 |