swamp_vm_debug_info/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use seq_map::SeqMap;
6use swamp_vm_types::types::FunctionInfo;
7use swamp_vm_types::{InstructionPosition, Meta};
8
9pub struct FileOffsetEntry {
10    pub start_pc: u32, // This u32 is the instruction index, so this should be plenty
11    pub pc_count: u8,  // A line can't cover more than 255 instructions
12    pub file_id: u16,  // Maximum 65535 files in a program
13    pub line_row: u16, // Can not have more than 65536 lines in a single source file
14}
15
16pub struct FileOffsetTable {
17    pub entries: Vec<FileOffsetEntry>,
18}
19
20impl Default for FileOffsetTable {
21    fn default() -> Self {
22        Self::new()
23    }
24}
25
26impl FileOffsetTable {
27    #[must_use]
28    pub const fn new() -> Self {
29        Self { entries: vec![] }
30    }
31    #[must_use]
32    pub fn find(&self, ip: InstructionPosition) -> Option<&FileOffsetEntry> {
33        let pc = ip.0;
34        self.entries
35            .iter()
36            .find(|&entry| pc >= entry.start_pc && pc <= entry.start_pc + u32::from(entry.pc_count))
37    }
38}
39
40pub struct FunctionDebugInfo {
41    pub start_pc: u32,
42    pub function_id: u16,
43}
44
45pub struct FunctionTable {
46    pub entries: Vec<FunctionDebugInfo>,
47}
48
49impl Default for FunctionTable {
50    fn default() -> Self {
51        Self::new()
52    }
53}
54
55impl FunctionTable {
56    #[must_use]
57    pub const fn new() -> Self {
58        Self { entries: vec![] }
59    }
60    pub(crate) fn find(&self, ip: InstructionPosition) -> Option<&FunctionDebugInfo> {
61        let pc = ip.0;
62        let mut last_info = None;
63        for entry in &self.entries {
64            if entry.start_pc > pc {
65                return last_info;
66            }
67            last_info = Some(entry);
68        }
69        last_info
70    }
71}
72
73pub struct DebugInfo {
74    pub function_lookup: SeqMap<u32, u8>,
75    pub file_offsets: FileOffsetTable,
76    pub function_table: FunctionTable,
77    pub info_for_each_instruction: Vec<Meta>,
78    pub function_infos: SeqMap<u16, FunctionInfo>,
79}
80
81pub struct DebugInfoForPc {
82    pub meta: Meta,
83    pub function_debug_info: FunctionInfo,
84}
85
86impl Default for DebugInfo {
87    fn default() -> Self {
88        Self::new()
89    }
90}
91
92impl DebugInfo {
93    #[must_use]
94    pub fn new() -> Self {
95        Self {
96            function_lookup: SeqMap::default(),
97            file_offsets: FileOffsetTable::new(),
98            function_table: FunctionTable::new(),
99            info_for_each_instruction: vec![],
100            function_infos: SeqMap::default(),
101        }
102    }
103
104    #[must_use]
105    pub fn fetch(&self, pc: usize) -> Option<DebugInfoForPc> {
106        let ip = InstructionPosition(pc as u32);
107        let function = self.function_table.find(ip)?;
108
109        let meta = &self.info_for_each_instruction[ip.0 as usize];
110
111        let func_info = self.function_infos.get(&function.function_id)?;
112
113        let info = DebugInfoForPc {
114            meta: Meta {
115                comment: meta.comment.clone(),
116                node: meta.node.clone(),
117            },
118            function_debug_info: func_info.clone(),
119        };
120
121        Some(info)
122    }
123}