gbf_core/decompiler/handlers/
mod.rs#![deny(missing_docs)]
use std::{collections::HashMap, sync::OnceLock};
use bin_op::BinaryOperationHandler;
use identifier::IdentifierHandler;
use literal::LiteralHandler;
use nop::NopHandler;
use variable_operand::VariableOperandHandler;
use crate::{instruction::Instruction, opcode::Opcode};
use super::{
function_decompiler::FunctionDecompilerError,
function_decompiler_context::FunctionDecompilerContext, ProcessedInstruction,
};
pub mod bin_op;
pub mod general;
pub mod identifier;
pub mod jump;
pub mod literal;
pub mod nop;
pub mod special_one_operand;
pub mod special_two_operand;
pub mod variable_operand;
pub trait OpcodeHandler: Send + Sync {
fn handle_instruction(
&self,
context: &mut FunctionDecompilerContext,
instruction: &Instruction,
) -> Result<ProcessedInstruction, FunctionDecompilerError>;
}
static GLOBAL_OPCODE_HANDLERS: OnceLock<HashMap<Opcode, Box<dyn OpcodeHandler>>> = OnceLock::new();
pub fn global_opcode_handlers() -> &'static HashMap<Opcode, Box<dyn OpcodeHandler>> {
GLOBAL_OPCODE_HANDLERS.get_or_init(|| {
let mut handlers: HashMap<Opcode, Box<dyn OpcodeHandler>> = HashMap::new();
handlers.insert(Opcode::Pop, Box::new(general::GeneralHandler));
handlers.insert(Opcode::Player, Box::new(IdentifierHandler));
handlers.insert(Opcode::PlayerO, Box::new(IdentifierHandler));
handlers.insert(Opcode::Temp, Box::new(IdentifierHandler));
handlers.insert(Opcode::Level, Box::new(IdentifierHandler));
handlers.insert(Opcode::This, Box::new(IdentifierHandler));
handlers.insert(Opcode::ThisO, Box::new(IdentifierHandler));
handlers.insert(Opcode::Params, Box::new(IdentifierHandler));
handlers.insert(Opcode::PushVariable, Box::new(IdentifierHandler));
handlers.insert(Opcode::PushString, Box::new(LiteralHandler));
handlers.insert(Opcode::PushNumber, Box::new(LiteralHandler));
handlers.insert(Opcode::Add, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::Subtract, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::Multiply, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::Divide, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::Modulo, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::BitwiseAnd, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::BitwiseOr, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::BitwiseXor, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::ShiftLeft, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::ShiftRight, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::Equal, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::NotEqual, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::LessThan, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::LessThanOrEqual, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::GreaterThan, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::GreaterThanOrEqual, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::ShortCircuitAnd, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::ShortCircuitOr, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::In, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::Join, Box::new(BinaryOperationHandler));
handlers.insert(Opcode::ConvertToFloat, Box::new(NopHandler));
handlers.insert(Opcode::ConvertToObject, Box::new(NopHandler));
handlers.insert(Opcode::FunctionStart, Box::new(NopHandler));
handlers.insert(Opcode::IncreaseLoopCounter, Box::new(NopHandler));
handlers.insert(
Opcode::AccessMember,
Box::new(special_two_operand::SpecialTwoOperandHandler),
);
handlers.insert(
Opcode::Assign,
Box::new(special_two_operand::SpecialTwoOperandHandler),
);
handlers.insert(
Opcode::Ret,
Box::new(special_one_operand::SpecialOneOperandHandler),
);
handlers.insert(Opcode::Call, Box::new(VariableOperandHandler));
handlers.insert(Opcode::EndParams, Box::new(VariableOperandHandler));
handlers.insert(Opcode::Jne, Box::new(jump::JumpHandler));
handlers
})
}