1use std::fmt::Write;
5
6use super::{Capture, CodeUnit, Format, Insn};
7use crate::heap::atom::{KeyKind, PropertyKey};
8
9pub fn register_name(unit: &CodeUnit, r: u32) -> String {
11 let parameters = unit.parameter_count as u32;
12 let locals = unit.temp_base() - 1 - parameters;
13 if unit.spill_register != super::NO_SPILL && r == unit.spill_register as u32 {
14 "spill".to_owned()
15 } else if r == 0 {
16 "this".to_owned()
17 } else if r <= parameters {
18 format!("p{}", r - 1)
19 } else if r <= parameters + locals {
20 format!("l{}", r - 1 - parameters)
21 } else if r < unit.register_count as u32 {
22 format!("t{}", r - unit.temp_base())
23 } else {
24 format!("r{r}")
25 }
26}
27
28pub fn key_placeholder(key: PropertyKey) -> String {
31 match key.kind() {
32 KeyKind::Index(index) => format!("[{index}]"),
33 KeyKind::String(id) => format!("atom#{}", id.index()),
34 KeyKind::Symbol(id) => format!("sym#{}", id.index()),
35 }
36}
37
38pub fn operands(
40 unit: &CodeUnit,
41 insn: Insn,
42 key_name: &mut dyn FnMut(PropertyKey) -> String,
43) -> String {
44 let r = |r: u8| register_name(unit, r as u32);
45 let target = |t: u32| format!("@{t}");
46 let text = match insn.op.format() {
47 Format::None => String::new(),
48 Format::A => r(insn.a),
49 Format::AB => format!("{}, {}", r(insn.a), r(insn.b)),
50 Format::ABC => format!("{}, {}, {}", r(insn.a), r(insn.b), r(insn.c)),
51 Format::AInt => format!("{}, {}", r(insn.a), insn.int()),
52 Format::ABInt => format!("{}, {}, {}", r(insn.a), r(insn.b), insn.int()),
53 Format::AConst => format!("{}, k{}", r(insn.a), insn.imm),
54 Format::Key => key_name(insn.key()),
55 Format::AKey => format!("{}, {}", r(insn.a), key_name(insn.key())),
56 Format::ABKey => format!("{}, {}, {}", r(insn.a), r(insn.b), key_name(insn.key())),
57 Format::ACapture => format!("{}, c{}", r(insn.a), insn.imm),
58 Format::ACount => format!("{}, {}", r(insn.a), insn.imm),
59 Format::ABRange => {
60 if insn.imm == 0 {
61 format!("{}, []", r(insn.a))
62 } else {
63 let last = insn.b as u32 + insn.imm - 1;
64 format!(
65 "{}, [{}..{}]",
66 r(insn.a),
67 r(insn.b),
68 register_name(unit, last)
69 )
70 }
71 }
72 Format::AChild => format!("{}, fn{}", r(insn.a), insn.imm),
73 Format::Call => format!("{}, {}, {}", r(insn.a), r(insn.b), insn.c),
74 Format::Jump => target(insn.imm),
75 Format::AJump => format!("{}, {}", r(insn.a), target(insn.imm)),
76 Format::ABJump => format!("{}, {}, {}", r(insn.a), r(insn.b), target(insn.imm)),
77 Format::AShortJump => format!("{}, {}, {}", r(insn.a), insn.short(), target(insn.imm)),
78 Format::AWide => format!("{}, {}", r(insn.a), register_name(unit, insn.imm)),
79 };
80 match insn.site() {
81 Some(site) => format!("{text}, ic{site}"),
82 None => text,
83 }
84}
85
86pub fn disassemble(unit: &CodeUnit, key_name: &mut dyn FnMut(PropertyKey) -> String) -> String {
88 let mut out = String::new();
89 let name = if unit.debug.name.is_empty() {
90 "<anonymous>"
91 } else {
92 &unit.debug.name
93 };
94 let _ = writeln!(
95 out,
96 "{name}: params {}, locals {}, registers {}, constants {}, children {}, this slots {}, cache sites {}",
97 unit.parameter_count,
98 unit.local_count,
99 unit.register_count,
100 unit.constant_count,
101 unit.children.len(),
102 unit.this_slots,
103 unit.ic_count
104 );
105 for (pc, &insn) in unit.code.iter().enumerate() {
106 let operands = operands(unit, insn, key_name);
107 let line = format!(" {pc:04} {:<20}{operands}", insn.op.name());
108 let _ = writeln!(out, "{}", line.trim_end());
109 }
110 for (index, capture) in unit.captures.iter().enumerate() {
111 let source = match *capture {
112 Capture::None => "none".to_owned(),
113 Capture::Register(r) => format!("parent {}", r),
114 Capture::Outer(i) => format!("parent c{i}"),
115 Capture::Slot(i) => format!("parent slot {i}"),
116 };
117 let _ = writeln!(out, " capture c{index} <- {source}");
118 }
119 for handler in &unit.handlers {
120 let _ = writeln!(
121 out,
122 " handler @{}..@{} -> @{}, {}",
123 handler.start,
124 handler.end,
125 handler.target,
126 register_name(unit, handler.register as u32)
127 );
128 }
129 out
130}