1use source_map_cache::SourceMapWrapper;
6use source_map_node::FileId;
7use std::fmt;
8use std::fmt::Write;
9use swamp_vm_debug_info::DebugInfo;
10use swamp_vm_disasm::disasm_instructions_color;
11use swamp_vm_types::types::{VariableRegister, VmType, show_frame_memory, write_basic_type};
12use swamp_vm_types::{BinaryInstruction, FrameMemoryAddress, InstructionRange};
13
14#[must_use]
15pub const fn is_valid_file_id(file_id: FileId) -> bool {
16 file_id != 0 && file_id != 0xffff
17}
18pub fn show_parameters_and_variables(
19 return_type: &VmType,
20 variables: &[VariableRegister],
21 f: &mut dyn Write,
22) -> Result<(), fmt::Error> {
23 if !return_type.is_scalar() {
24 writeln!(f, "{}: {}", tinter::blue("r0"), &return_type,)?;
25 write_basic_type(&return_type.basic_type, FrameMemoryAddress(0), f, 0)?;
26 writeln!(f)?;
27 }
28
29 for variable_register in variables {
30 writeln!(
31 f,
32 "var{}: ({}): {} {}",
33 tinter::yellow(format!("{}", variable_register.unique_id_in_function)),
34 tinter::magenta(variable_register),
35 variable_register.register.ty,
36 variable_register.register.comment
37 )?;
38 }
39
40 Ok(())
41}
42
43#[must_use]
46pub fn disasm_function(
47 return_type: &VmType,
48 instructions: &[BinaryInstruction],
49 range: &InstructionRange,
50 debug_info: &DebugInfo,
51 source_map_wrapper: &SourceMapWrapper,
52 use_color: bool,
53) -> String {
54 let mut header_output = String::new();
55
56 let info = debug_info.fetch(range.start.0 as usize).unwrap();
57
58 show_frame_memory(
59 &info.function_debug_info.frame_memory,
60 &mut header_output,
61 use_color,
62 )
63 .unwrap();
64
65 show_parameters_and_variables(
66 return_type,
67 &info.function_debug_info.frame_memory.variable_registers,
68 &mut header_output,
69 )
70 .expect("should work");
71
72 let asm = disasm_instructions_color(
73 instructions,
74 range,
75 debug_info,
76 source_map_wrapper,
77 use_color,
78 );
79
80 format!("{header_output}\n{asm}",)
81}
82
83pub fn disasm_whole_program(
84 debug_info: &DebugInfo,
85 source_map_wrapper: &SourceMapWrapper,
86 instructions: &[BinaryInstruction],
87 use_color: bool,
88) {
89 let mut current_ip: u32 = 0;
90
91 while current_ip < (instructions.len() - 1) as u32 {
92 if let Some(debug_info_for_pc) = debug_info.fetch(current_ip as usize) {
93 println!(
95 "{} ==========================================================================",
96 debug_info_for_pc.function_debug_info.name
97 );
98 let end_ip = current_ip + debug_info_for_pc.function_debug_info.ip_range.count.0;
99 let output_string = disasm_function(
102 &debug_info_for_pc.function_debug_info.return_type,
103 instructions,
104 &debug_info_for_pc.function_debug_info.ip_range,
105 debug_info,
106 source_map_wrapper,
107 use_color,
108 );
109 println!("{output_string}"); current_ip = end_ip;
111 } else {
112 panic!("instruction pointer that is not covered")
113 }
114 }
115}