portal_pc_waffle/ir/debug.rs
1//! Debug info (currently, source-location maps).
2
3use crate::declare_entity;
4use crate::entity::EntityVec;
5// use addr2line::gimli;
6use alloc::borrow::ToOwned;
7use alloc::string::String;
8use alloc::vec;
9use alloc::vec::Vec;
10use hashbrown::hash_map::Entry as HashEntry;
11use hashbrown::HashMap;
12
13declare_entity!(SourceFile, "file");
14declare_entity!(SourceLoc, "loc");
15
16#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
17pub struct Debug {
18 /// Interned source-file names, indexed by a `SourceFile` entity
19 /// index.
20 pub source_files: EntityVec<SourceFile, String>,
21 source_file_dedup: HashMap<String, SourceFile>,
22 /// Interned source locations (file, line, and column),, indexed
23 /// by a `SourceLoc` entity index.
24 pub source_locs: EntityVec<SourceLoc, SourceLocData>,
25 source_loc_dedup: HashMap<SourceLocData, SourceLoc>,
26}
27
28#[derive(
29 Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize,
30)]
31/// A "source location": a filename (interned to an ID), a line, and a
32/// column.
33
34pub struct SourceLocData {
35 pub file: SourceFile,
36 pub line: u32,
37 pub col: u32,
38}
39
40impl Debug {
41 /// Intern a filename to an ID.
42 pub fn intern_file(&mut self, path: &str) -> SourceFile {
43 if let Some(id) = self.source_file_dedup.get(path) {
44 return *id;
45 }
46 let id = self.source_files.push(path.to_owned());
47 self.source_file_dedup.insert(path.to_owned(), id);
48 id
49 }
50
51 /// Intern a location (line and column) in an already-interned
52 /// filename.
53 pub fn intern_loc(&mut self, file: SourceFile, line: u32, col: u32) -> SourceLoc {
54 let data = SourceLocData { file, line, col };
55 match self.source_loc_dedup.entry(data) {
56 HashEntry::Vacant(v) => {
57 let id = self.source_locs.push(data);
58 *v.insert(id)
59 }
60 HashEntry::Occupied(o) => *o.get(),
61 }
62 }
63}
64
65#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
66/// A map from ranges of offsets in the original Wasm file to source
67/// locations.
68
69pub struct DebugMap {
70 /// Offset of code section relative to the Wasm file start.
71 pub code_offset: u32,
72 /// Each tuple is `(start, len, loc)`. The `start` offset is
73 /// relative to the code section.
74 pub tuples: Vec<(u32, u32, SourceLoc)>,
75}
76
77impl DebugMap {
78 // pub(crate) fn from_dwarf<R: gimli::Reader>(
79 // // dwarf: gimli::Dwarf<R>,
80 // debug: &mut Debug,
81 // code_offset: u32,
82 // ) -> anyhow::Result<DebugMap> {
83 // anyhow::bail!("todo: reimplement or use no_std dwarf")
84 // let ctx = addr2line::Context::from_dwarf(dwarf)?;
85 // let mut tuples = vec![];
86
87 // let mut locs = ctx.find_location_range(0, u64::MAX).unwrap();
88 // while let Some((start, len, loc)) = locs.next() {
89 // let file = debug.intern_file(loc.file.unwrap_or(""));
90 // let loc = debug.intern_loc(file, loc.line.unwrap_or(0), loc.column.unwrap_or(0));
91 // log::trace!("tuple: loc {} start {:x} len {:x}", loc, start, len);
92 // tuples.push((start as u32, len as u32, loc));
93 // }
94 // tuples.sort();
95
96 // let mut last = 0;
97 // tuples.retain(|&(start, len, _)| {
98 // let retain = start >= last;
99 // if retain {
100 // last = start + len;
101 // }
102 // retain
103 // });
104
105 // Ok(DebugMap {
106 // code_offset,
107 // tuples,
108 // })
109 // }
110}