use crate::recompiler::ir::instruction::IRFunction;
use anyhow::Result;
pub struct IRToRust;
impl IRToRust {
#[inline] pub fn translate(function: &IRFunction) -> Result<String> {
let estimated_capacity: usize = function.basic_blocks.iter()
.map(|block| block.instructions.len())
.sum::<usize>() * 100usize;
let mut code: String = String::with_capacity(estimated_capacity);
code.push_str(&format!("fn {}() {{\n", function.name));
code.push_str(" let mut ctx = gcrecomp_runtime::CpuContext::new();\n");
code.push_str(" let mut memory = gcrecomp_runtime::MemoryManager::new();\n");
code.push('\n');
for block in function.basic_blocks.iter() {
for inst in block.instructions.iter() {
code.push_str(&Self::translate_instruction(inst)?);
}
}
code.push_str("}\n");
Ok(code)
}
#[inline] fn translate_instruction(inst: &crate::recompiler::ir::instruction::IRInstruction) -> Result<String> {
match inst {
crate::recompiler::ir::instruction::IRInstruction::Add { dst, src1, src2 } => {
Ok(format!(
" ctx.set_register({}, ctx.get_register({}) + ctx.get_register({}));\n",
dst, src1, src2
))
}
crate::recompiler::ir::instruction::IRInstruction::Sub { dst, src1, src2 } => {
Ok(format!(
" ctx.set_register({}, ctx.get_register({}) - ctx.get_register({}));\n",
dst, src1, src2
))
}
crate::recompiler::ir::instruction::IRInstruction::Mul { dst, src1, src2 } => {
Ok(format!(
" ctx.set_register({}, ctx.get_register({}) * ctx.get_register({}));\n",
dst, src1, src2
))
}
crate::recompiler::ir::instruction::IRInstruction::Div { dst, src1, src2 } => {
Ok(format!(
" ctx.set_register({}, ctx.get_register({}) / ctx.get_register({}));\n",
dst, src1, src2
))
}
crate::recompiler::ir::instruction::IRInstruction::Move { dst, src } => {
Ok(format!(
" ctx.set_register({}, ctx.get_register({}));\n",
dst, src
))
}
crate::recompiler::ir::instruction::IRInstruction::MoveImm { dst, imm } => {
Ok(format!(
" ctx.set_register({}, {}u32);\n",
dst, imm
))
}
_ => Ok(" // IR instruction\n".to_string()),
}
}
}