summaryrefslogtreecommitdiff
path: root/crates/cli/src/cmd/dump.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/cli/src/cmd/dump.rs')
-rw-r--r--crates/cli/src/cmd/dump.rs71
1 files changed, 71 insertions, 0 deletions
diff --git a/crates/cli/src/cmd/dump.rs b/crates/cli/src/cmd/dump.rs
new file mode 100644
index 0000000..78fb28b
--- /dev/null
+++ b/crates/cli/src/cmd/dump.rs
@@ -0,0 +1,71 @@
+use anstream::println;
+use eyre::Result;
+use owo_colors::OwoColorize;
+use tinywasm::types::{ExternalKind, ImportKind};
+
+use crate::cli::ModuleInputArgs;
+use crate::load::load_module;
+
+pub fn run(args: ModuleInputArgs) -> Result<()> {
+ let loaded = load_module(&args.module)?;
+ let module = loaded.module;
+
+ let imported_func_count =
+ module.imports.iter().filter(|import| matches!(import.kind, ImportKind::Function(_))).count() as u32;
+
+ for (func_idx, func) in module.funcs.iter().enumerate() {
+ let global_idx = imported_func_count + func_idx as u32;
+
+ let exports = module
+ .exports
+ .iter()
+ .filter(|export| export.kind == ExternalKind::Func && export.index == global_idx)
+ .map(|export| export.name.as_ref())
+ .collect::<Vec<_>>();
+
+ let header = format!("func[{func_idx}]").blue().bold().to_string();
+ if exports.is_empty() {
+ println!("{header}");
+ } else {
+ println!("{header} {}", format!("exports={}", format!("{exports:?}").cyan()).bright_black());
+ }
+
+ for (ip, instr) in func.instructions.iter().enumerate() {
+ let instr = print_instr(instr);
+ println!(" {}: {}", print_ip(ip), instr);
+ }
+ println!();
+ }
+
+ Ok(())
+}
+
+fn print_ip(ip: usize) -> String {
+ let s = format!("{ip:04}");
+ let first_non_zero = s.find(|c| c != '0').unwrap_or(s.len() - 1);
+
+ format!(
+ "{}{}",
+ &s[..first_non_zero].to_string().bright_black().dimmed(),
+ &s[first_non_zero..].to_string().bright_black()
+ )
+}
+
+fn print_instr(instr: &tinywasm::types::Instruction) -> String {
+ let instr = format!("{instr:?}");
+ let Some(split) = instr.find(['(', ' ', '{']) else {
+ return instr.bold().to_string();
+ };
+
+ let (name, rest) = instr.split_at(split);
+
+ let rest = rest
+ .replace('(', &"(".bright_black().to_string())
+ .replace(')', &")".bright_black().to_string())
+ .replace('{', &"{".bright_black().to_string())
+ .replace('}', &"}".bright_black().to_string())
+ .replace(',', &",".bright_black().to_string())
+ .replace(':', &":".bright_black().to_string());
+
+ format!("{}{}", name.bold(), rest)
+}