gbf_core/decompiler/handlers/
bin_op.rs

1#![deny(missing_docs)]
2
3use std::backtrace::Backtrace;
4
5use crate::{
6    decompiler::{
7        ProcessedInstruction, ProcessedInstructionBuilder,
8        ast::{bin_op::BinOpType, new_bin_op},
9        function_decompiler::FunctionDecompilerError,
10        function_decompiler_context::FunctionDecompilerContext,
11    },
12    instruction::Instruction,
13    opcode::Opcode,
14};
15
16use super::OpcodeHandler;
17
18/// Handles identifier instructions.
19pub struct BinaryOperationHandler;
20
21impl OpcodeHandler for BinaryOperationHandler {
22    fn handle_instruction(
23        &self,
24        context: &mut FunctionDecompilerContext,
25        instruction: &Instruction,
26    ) -> Result<ProcessedInstruction, FunctionDecompilerError> {
27        let rhs = context.pop_expression()?;
28        let lhs = context.pop_expression()?;
29
30        let op_type = match instruction.opcode {
31            Opcode::Add => BinOpType::Add,
32            Opcode::Subtract => BinOpType::Sub,
33            Opcode::Multiply => BinOpType::Mul,
34            Opcode::Divide => BinOpType::Div,
35            Opcode::Modulo => BinOpType::Mod,
36            Opcode::BitwiseAnd => BinOpType::And,
37            Opcode::BitwiseOr => BinOpType::Or,
38            Opcode::BitwiseXor => BinOpType::Xor,
39            Opcode::ShiftLeft => BinOpType::ShiftLeft,
40            Opcode::ShiftRight => BinOpType::ShiftRight,
41            Opcode::Equal => BinOpType::Equal,
42            Opcode::NotEqual => BinOpType::NotEqual,
43            Opcode::LessThan => BinOpType::Less,
44            Opcode::LessThanOrEqual => BinOpType::LessOrEqual,
45            Opcode::GreaterThan => BinOpType::Greater,
46            Opcode::GreaterThanOrEqual => BinOpType::GreaterOrEqual,
47            Opcode::ShortCircuitAnd => BinOpType::LogicalAnd,
48            Opcode::ShortCircuitOr => BinOpType::LogicalOr,
49            Opcode::In => BinOpType::In,
50            Opcode::Join => BinOpType::Join,
51            Opcode::Power => BinOpType::Power,
52            _ => {
53                return Err(FunctionDecompilerError::UnimplementedOpcode {
54                    opcode: instruction.opcode,
55                    context: context.get_error_context(),
56                    backtrace: Backtrace::capture(),
57                });
58            }
59        };
60
61        let op =
62            new_bin_op(lhs, rhs, op_type).map_err(|e| FunctionDecompilerError::AstNodeError {
63                source: e,
64                context: context.get_error_context(),
65                backtrace: Backtrace::capture(),
66            })?;
67        // let var = context.ssa_context.new_ssa_version_for("bin_op");
68        // let ssa_id = new_id_with_version("bin_op", var);
69        // let stmt = new_assignment(ssa_id.clone(), op);
70        context.push_one_node(op.into())?;
71
72        Ok(ProcessedInstructionBuilder::new().build())
73    }
74}