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