Skip to main content

ironwork_rt/lir/
debug.rs

1//! The debug table (lir.md §10), with positions encoded as differences (load-module.md §9).
2
3use super::{DebugId, SymId};
4use crate::module::ModuleError;
5use crate::module::codec::{Decode, Encode, Reader, Writer};
6use crate::vocab::Pos;
7
8/// `positions` maps a DebugId to its position; `ops` holds, per block, one per op and one for the terminator.
9#[derive(Clone, Debug, Default, PartialEq, Eq)]
10pub struct Debug {
11    pub sources: Vec<SymId>,
12    pub positions: Vec<Pos>,
13    pub ops: Vec<Vec<DebugId>>,
14}
15
16impl Encode for Debug {
17    fn encode(&self, w: &mut Writer) {
18        self.sources.encode(w);
19        w.count(self.positions.len());
20        let mut last = Pos::default();
21        for &pos in &self.positions {
22            w.zigzag(i64::from(pos.file) - i64::from(last.file));
23            w.zigzag(i64::from(pos.line) - i64::from(last.line));
24            w.zigzag(i64::from(pos.col) - i64::from(last.col));
25            last = pos;
26        }
27        self.ops.encode(w);
28    }
29}
30
31impl Decode for Debug {
32    fn decode(r: &mut Reader<'_>) -> Result<Self, ModuleError> {
33        let sources = Vec::decode(r)?;
34        let count = r.count()?;
35        let mut positions = Vec::with_capacity(count);
36        let mut last = Pos::default();
37        for _ in 0..count {
38            let pos = Pos {
39                file: moved(r, "file", last.file)?,
40                line: moved(r, "line", last.line)?,
41                col: moved(r, "column", last.col)?,
42            };
43            positions.push(pos);
44            last = pos;
45        }
46        let ops = Vec::decode(r)?;
47        Ok(Self { sources, positions, ops })
48    }
49}
50
51fn moved<T: Into<i64> + TryFrom<i64>>(r: &mut Reader<'_>, what: &str, from: T) -> Result<T, ModuleError> {
52    let at = r.position();
53    let delta = r.zigzag()?;
54    let value = from.into().checked_add(delta);
55    value
56        .and_then(|v| T::try_from(v).ok())
57        .ok_or_else(|| r.malformed(at, format!("a {what} of {}", value.map_or_else(|| "over 64 bits".to_owned(), |v| v.to_string()))))
58}