Skip to main content

wamex_cli/analysis/
debug.rs

1use std::fmt::Debug;
2
3use crate::{
4    analysis::{
5        self,
6        dep_graph::{DepGraph, DepSet},
7        split_point::OutputModuleInfo,
8        symbols::{SymbolKind, SymbolRecord},
9    },
10    helpers::debug_fmt_mostly_filled,
11    index::SymbolId,
12};
13
14pub(crate) fn print_deps_inner(
15    module_name: &str,
16    info: &analysis::ModuleInfo,
17    reachable: &DepSet,
18    graph: &DepGraph,
19) {
20    let size_fn = |symbol: &SymbolRecord| match symbol.kind {
21        SymbolKind::DataDefined { length, .. } => length,
22        SymbolKind::Func { input_id } => {
23            if let Some(defined_id) = info.as_defined_function_id(input_id) {
24                info.wasm.code.defined_funcs[defined_id].body.range().len()
25            } else {
26                0
27            }
28        }
29        _ => unreachable!(),
30    };
31    let format_dep = |dep: SymbolId| {
32        let symbol = info.symbols.get(dep).expect("dep should be valid");
33        let name = crate::helpers::demangle_full(&symbol.name);
34        match symbol.kind {
35            SymbolKind::Func { input_id } => {
36                format!(
37                    "{dep} func[{input_id}] <{name:?}> (size={})",
38                    size_fn(symbol)
39                )
40            }
41            SymbolKind::DataDefined {
42                segment_id,
43                offset,
44                length,
45                ..
46            } => {
47                let segment_name = info
48                    .wasm
49                    .names
50                    .data_segments
51                    .get(segment_id)
52                    .cloned()
53                    .unwrap_or_default();
54                format!(
55                    "{dep} data[{segment_name}({segment_id}):{start}..{end}]  <{name:?}> (size={})",
56                    size_fn(symbol),
57                    start = offset,
58                    end = offset + length
59                )
60            }
61            _ => unreachable!(),
62        }
63    };
64
65    println!("SPLIT: ============== {module_name}");
66    for (node, children) in graph.iter_childs() {
67        if !reachable.contains(&node) {
68            continue;
69        }
70
71        println!("---{}---", format_dep(node));
72        for parent in graph.get_parents(node).into_iter().flatten() {
73            println!("<=={} (parent)", format_dep(*parent));
74        }
75        println!("-------------");
76        for child in children {
77            println!("==>{}", format_dep(*child));
78        }
79    }
80
81    let mut total_size: usize = 0;
82    for r in reachable.iter() {
83        let symbol = info.symbols.get(*r).expect("dep should be valid");
84        total_size += size_fn(symbol);
85    }
86    println!("SPLIT: ============== {module_name} : total size: {total_size}");
87}
88
89impl Debug for OutputModuleInfo {
90    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91        let mut defined_symbols = self.defined_symbols.iter().copied().collect::<Vec<_>>();
92
93        let mut imported_symbols = self.imports.iter().copied().collect::<Vec<_>>();
94
95        let mut exported_symbols = self.exports.iter().copied().collect::<Vec<_>>();
96
97        defined_symbols.sort_unstable();
98        imported_symbols.sort_unstable();
99        exported_symbols.sort_unstable();
100
101        f.debug_struct("OutputModuleInfo")
102            .field(
103                "imported_symbols",
104                &debug_fmt_mostly_filled(&imported_symbols, 3, 7, "...", |a, b| a.next() != *b),
105            )
106            .field(
107                "exported_symbols",
108                &debug_fmt_mostly_filled(&exported_symbols, 3, 7, "...", |a, b| a.next() != *b),
109            )
110            .field(
111                "defined_symbols",
112                &debug_fmt_mostly_filled(&defined_symbols, 3, 7, "...", |a, b| a.next() != *b),
113            )
114            .finish()
115    }
116}
117
118impl OutputModuleInfo {
119    pub fn print(&self, module_name: &str, info: &analysis::ModuleInfo, graph: &DepGraph) {
120        print_deps_inner(module_name, info, &self.defined_symbols, graph);
121    }
122}