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