1pub mod binja;
7pub mod cpp;
8pub mod ida;
9pub mod rust;
10
11use crate::config::GenTarget;
12use crate::types::ValidatedDef;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum OperandKind {
17 Register,
18 Immediate,
19 Address,
20 Memory,
21}
22
23#[derive(Debug, Clone, Default)]
25pub struct FlowConfig {
26 pub calls: Vec<String>,
27 pub branches: Vec<String>,
28 pub unconditional_branches: Vec<String>,
29 pub returns: Vec<String>,
30 pub stops: Vec<String>,
31}
32
33pub trait CodegenBackend {
35 fn lang(&self) -> &str;
37
38 fn generate(&self, ir: &ValidatedDef, config: &GenTarget) -> Result<String, CodegenError>;
40
41 fn formatter_command(&self) -> Option<&[&str]>;
43}
44
45#[derive(Debug)]
46pub enum CodegenError {
47 Internal(String),
48}
49
50impl std::fmt::Display for CodegenError {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 match self {
53 CodegenError::Internal(msg) => write!(f, "codegen error: {}", msg),
54 }
55 }
56}
57
58impl std::error::Error for CodegenError {}
59
60pub fn get_backend(lang: &str) -> Option<Box<dyn CodegenBackend>> {
62 match lang {
63 "rust" => Some(Box::new(rust::RustBackend)),
64 "ida" => Some(Box::new(ida::IdaBackend)),
65 "binja" => Some(Box::new(binja::BinjaBackend)),
66 "cpp" => Some(Box::new(cpp::CppBackend)),
67 _ => None,
68 }
69}
70
71pub fn run_formatter(cmd: &[&str], path: &str) {
73 let status = std::process::Command::new(cmd[0])
74 .args(&cmd[1..])
75 .arg(path)
76 .status();
77
78 match status {
79 Ok(s) if s.success() => {}
80 Ok(s) => eprintln!("warning: formatter exited with {}", s),
81 Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
82 eprintln!("warning: formatter '{}' not found, skipping", cmd[0]);
83 }
84 Err(e) => eprintln!("warning: failed to run formatter: {}", e),
85 }
86}