gbf_core/decompiler/handlers/
bin_op.rs1#![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
18pub 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 context.push_one_node(op.into())?;
71
72 Ok(ProcessedInstructionBuilder::new().build())
73 }
74}