1use crate::bytecode::InstIter;
2use alloy_primitives::map::rustc_hash::FxHashMap;
3use serde::Serialize;
4
5#[derive(Debug, Clone, Serialize)]
9#[serde(transparent)]
10pub struct PcIcMap {
11 pub inner: FxHashMap<u32, u32>,
12}
13
14impl PcIcMap {
15 pub fn new(code: &[u8]) -> Self {
17 Self { inner: make_map::<true>(code) }
18 }
19
20 pub fn len(&self) -> usize {
22 self.inner.len()
23 }
24
25 pub fn is_empty(&self) -> bool {
27 self.inner.is_empty()
28 }
29
30 pub fn get(&self, pc: u32) -> Option<u32> {
32 self.inner.get(&pc).copied()
33 }
34}
35
36pub struct IcPcMap {
40 pub inner: FxHashMap<u32, u32>,
41}
42
43impl IcPcMap {
44 pub fn new(code: &[u8]) -> Self {
46 Self { inner: make_map::<false>(code) }
47 }
48
49 pub fn len(&self) -> usize {
51 self.inner.len()
52 }
53
54 pub fn is_empty(&self) -> bool {
56 self.inner.is_empty()
57 }
58
59 pub fn get(&self, ic: u32) -> Option<u32> {
61 self.inner.get(&ic).copied()
62 }
63}
64
65fn make_map<const PC_FIRST: bool>(code: &[u8]) -> FxHashMap<u32, u32> {
66 assert!(code.len() <= u32::MAX as usize, "bytecode is too big");
67 let mut map = FxHashMap::with_capacity_and_hasher(code.len(), Default::default());
68 for (ic, (pc, _)) in InstIter::new(code).with_pc().enumerate() {
69 if PC_FIRST {
70 map.insert(pc as u32, ic as u32);
71 } else {
72 map.insert(ic as u32, pc as u32);
73 }
74 }
75 map.shrink_to_fit();
76 map
77}