gbf_core/decompiler/handlers/
mod.rs

1#![deny(missing_docs)]
2
3use std::{collections::HashMap, sync::OnceLock};
4
5use bin_op::BinaryOperationHandler;
6use identifier::IdentifierHandler;
7use literal::LiteralHandler;
8use nop::NopHandler;
9use variable_operand::VariableOperandHandler;
10
11use crate::{instruction::Instruction, opcode::Opcode};
12
13use super::{
14    ProcessedInstruction, function_decompiler::FunctionDecompilerError,
15    function_decompiler_context::FunctionDecompilerContext,
16};
17
18/// Handles binary operation instructions.
19pub mod bin_op;
20/// Contains built-in handlers for instructions.
21pub mod builtins;
22/// Contains general handlers for instructions.
23pub mod general;
24/// Handles identifier instructions.
25pub mod identifier;
26/// Handles jump instructions.
27pub mod jump;
28/// Handles literal instructions.
29pub mod literal;
30/// Handles instructions that are not useful to our decompiler.
31pub mod nop;
32/// Handles short-circuit instructions.
33pub mod short_circuit;
34/// Handles instructions with one operand.
35pub mod special_one_operand;
36/// Handles instructinos with three operands.
37pub mod special_three_operand;
38/// Handles instructions with two operands.
39pub mod special_two_operand;
40/// Handles unary operation instructions.
41pub mod un_op;
42/// Handles cases with a variable number of operands.
43pub mod variable_operand;
44
45/// Represents an opcode handler for the decompiler.
46pub trait OpcodeHandler: Send + Sync {
47    /// Handles the given instruction.
48    ///
49    /// # Arguments
50    /// - `context`: The decompiler context.
51    /// - `instruction`: The instruction to handle.
52    ///
53    /// # Errors
54    /// - Returns a `FunctionDecompilerError` if there is an issue handling the instruction.
55    fn handle_instruction(
56        &self,
57        context: &mut FunctionDecompilerContext,
58        instruction: &Instruction,
59    ) -> Result<ProcessedInstruction, FunctionDecompilerError>;
60}
61
62static GLOBAL_OPCODE_HANDLERS: OnceLock<HashMap<Opcode, Box<dyn OpcodeHandler>>> = OnceLock::new();
63
64/// Gets the global opcode handlers.
65pub fn global_opcode_handlers() -> &'static HashMap<Opcode, Box<dyn OpcodeHandler>> {
66    GLOBAL_OPCODE_HANDLERS.get_or_init(|| {
67        let mut handlers: HashMap<Opcode, Box<dyn OpcodeHandler>> = HashMap::new();
68
69        // General cases
70        handlers.insert(Opcode::Pop, Box::new(general::GeneralHandler));
71
72        // These handlers are used to create identifier nodes. All of them, with the
73        // exception of `PushVariable`, use the lowercase opcode name as the identifier
74        // name.
75        handlers.insert(Opcode::Player, Box::new(IdentifierHandler));
76        handlers.insert(Opcode::PlayerO, Box::new(IdentifierHandler));
77        handlers.insert(Opcode::Temp, Box::new(IdentifierHandler));
78        handlers.insert(Opcode::Level, Box::new(IdentifierHandler));
79        handlers.insert(Opcode::This, Box::new(IdentifierHandler));
80        handlers.insert(Opcode::ThisO, Box::new(IdentifierHandler));
81        handlers.insert(Opcode::Params, Box::new(IdentifierHandler));
82        handlers.insert(Opcode::PushVariable, Box::new(IdentifierHandler));
83        handlers.insert(Opcode::Pi, Box::new(IdentifierHandler));
84
85        // These handlers are used to create literal nodes.
86        handlers.insert(Opcode::PushString, Box::new(LiteralHandler));
87        handlers.insert(Opcode::PushNumber, Box::new(LiteralHandler));
88        handlers.insert(Opcode::PushTrue, Box::new(LiteralHandler));
89        handlers.insert(Opcode::PushFalse, Box::new(LiteralHandler));
90        handlers.insert(Opcode::PushNull, Box::new(LiteralHandler));
91
92        // These handlers are used to create unary operation nodes.
93        handlers.insert(Opcode::LogicalNot, Box::new(un_op::UnaryOperationHandler));
94        handlers.insert(
95            Opcode::BitwiseInvert,
96            Box::new(un_op::UnaryOperationHandler),
97        );
98        handlers.insert(
99            Opcode::UnarySubtract,
100            Box::new(un_op::UnaryOperationHandler),
101        );
102
103        // These handlers are used to create binary operation nodes.
104        handlers.insert(Opcode::Add, Box::new(BinaryOperationHandler));
105        handlers.insert(Opcode::Subtract, Box::new(BinaryOperationHandler));
106        handlers.insert(Opcode::Multiply, Box::new(BinaryOperationHandler));
107        handlers.insert(Opcode::Divide, Box::new(BinaryOperationHandler));
108        handlers.insert(Opcode::Modulo, Box::new(BinaryOperationHandler));
109        handlers.insert(Opcode::BitwiseAnd, Box::new(BinaryOperationHandler));
110        handlers.insert(Opcode::BitwiseOr, Box::new(BinaryOperationHandler));
111        handlers.insert(Opcode::BitwiseXor, Box::new(BinaryOperationHandler));
112        handlers.insert(Opcode::ShiftLeft, Box::new(BinaryOperationHandler));
113        handlers.insert(Opcode::ShiftRight, Box::new(BinaryOperationHandler));
114        handlers.insert(Opcode::Equal, Box::new(BinaryOperationHandler));
115        handlers.insert(Opcode::NotEqual, Box::new(BinaryOperationHandler));
116        handlers.insert(Opcode::LessThan, Box::new(BinaryOperationHandler));
117        handlers.insert(Opcode::LessThanOrEqual, Box::new(BinaryOperationHandler));
118        handlers.insert(Opcode::GreaterThan, Box::new(BinaryOperationHandler));
119        handlers.insert(Opcode::GreaterThanOrEqual, Box::new(BinaryOperationHandler));
120        handlers.insert(Opcode::In, Box::new(BinaryOperationHandler));
121        handlers.insert(Opcode::Join, Box::new(BinaryOperationHandler));
122        handlers.insert(Opcode::Power, Box::new(BinaryOperationHandler));
123
124        // These opcodes do nothing ATM
125        handlers.insert(Opcode::ConvertToFloat, Box::new(NopHandler));
126        handlers.insert(Opcode::ConvertToObject, Box::new(NopHandler));
127        handlers.insert(Opcode::ConvertToString, Box::new(NopHandler));
128        handlers.insert(Opcode::ConvertToVariable, Box::new(NopHandler));
129        handlers.insert(Opcode::FunctionStart, Box::new(NopHandler));
130        handlers.insert(Opcode::IncreaseLoopCounter, Box::new(NopHandler));
131        handlers.insert(Opcode::Jmp, Box::new(NopHandler));
132        handlers.insert(Opcode::MarkRegisterVariable, Box::new(NopHandler));
133        handlers.insert(Opcode::WithEnd, Box::new(NopHandler));
134        handlers.insert(Opcode::ShortCircuitEnd, Box::new(NopHandler));
135
136        // Three operand handlers
137        handlers.insert(
138            Opcode::AssignArray,
139            Box::new(special_three_operand::SpecialThreeOperandHandler),
140        );
141        handlers.insert(
142            Opcode::InRange,
143            Box::new(special_three_operand::SpecialThreeOperandHandler),
144        );
145        handlers.insert(
146            Opcode::AssignMultiDimensionalArrayIndex,
147            Box::new(special_three_operand::SpecialThreeOperandHandler),
148        );
149        handlers.insert(
150            Opcode::AssignMultiDimensionalArray,
151            Box::new(special_three_operand::SpecialThreeOperandHandler),
152        );
153
154        // Two operand handlers
155        handlers.insert(
156            Opcode::AccessMember,
157            Box::new(special_two_operand::SpecialTwoOperandHandler),
158        );
159        handlers.insert(
160            Opcode::Assign,
161            Box::new(special_two_operand::SpecialTwoOperandHandler),
162        );
163        handlers.insert(
164            Opcode::ArrayAccess,
165            Box::new(special_two_operand::SpecialTwoOperandHandler),
166        );
167        handlers.insert(
168            Opcode::NewObject,
169            Box::new(special_two_operand::SpecialTwoOperandHandler),
170        );
171
172        // One operand handlers
173        handlers.insert(
174            Opcode::Ret,
175            Box::new(special_one_operand::SpecialOneOperandHandler),
176        );
177        handlers.insert(
178            Opcode::Copy,
179            Box::new(special_one_operand::SpecialOneOperandHandler),
180        );
181        handlers.insert(
182            Opcode::SetRegister,
183            Box::new(special_one_operand::SpecialOneOperandHandler),
184        );
185        handlers.insert(
186            Opcode::GetRegister,
187            Box::new(special_one_operand::SpecialOneOperandHandler),
188        );
189        handlers.insert(
190            Opcode::Inc,
191            Box::new(special_one_operand::SpecialOneOperandHandler),
192        );
193        handlers.insert(
194            Opcode::Dec,
195            Box::new(special_one_operand::SpecialOneOperandHandler),
196        );
197        handlers.insert(
198            Opcode::New,
199            Box::new(special_one_operand::SpecialOneOperandHandler),
200        );
201        handlers.insert(
202            Opcode::NewUninitializedArray,
203            Box::new(special_one_operand::SpecialOneOperandHandler),
204        );
205
206        // Variable operand handlers
207        handlers.insert(Opcode::Call, Box::new(VariableOperandHandler));
208        handlers.insert(Opcode::EndParams, Box::new(VariableOperandHandler));
209        handlers.insert(Opcode::EndArray, Box::new(VariableOperandHandler));
210
211        // Builtin handlers
212        handlers.insert(Opcode::Char, Box::new(builtins::BuiltinsHandler));
213        handlers.insert(Opcode::Int, Box::new(builtins::BuiltinsHandler));
214        handlers.insert(Opcode::Random, Box::new(builtins::BuiltinsHandler));
215        handlers.insert(Opcode::Abs, Box::new(builtins::BuiltinsHandler));
216        handlers.insert(Opcode::Sin, Box::new(builtins::BuiltinsHandler));
217        handlers.insert(Opcode::Cos, Box::new(builtins::BuiltinsHandler));
218        handlers.insert(Opcode::VecX, Box::new(builtins::BuiltinsHandler));
219        handlers.insert(Opcode::VecY, Box::new(builtins::BuiltinsHandler));
220        handlers.insert(Opcode::Sleep, Box::new(builtins::BuiltinsHandler));
221        handlers.insert(Opcode::ArcTan, Box::new(builtins::BuiltinsHandler));
222        handlers.insert(Opcode::MakeVar, Box::new(builtins::BuiltinsHandler));
223        handlers.insert(Opcode::GetTranslation, Box::new(builtins::BuiltinsHandler));
224        handlers.insert(Opcode::Min, Box::new(builtins::BuiltinsHandler));
225        handlers.insert(Opcode::Max, Box::new(builtins::BuiltinsHandler));
226        handlers.insert(Opcode::WaitFor, Box::new(builtins::BuiltinsHandler));
227        handlers.insert(Opcode::GetAngle, Box::new(builtins::BuiltinsHandler));
228        handlers.insert(Opcode::GetDir, Box::new(builtins::BuiltinsHandler));
229        handlers.insert(Opcode::Format, Box::new(builtins::BuiltinsHandler));
230
231        handlers.insert(Opcode::ObjSubstring, Box::new(builtins::BuiltinsHandler));
232        handlers.insert(Opcode::ObjTokenize, Box::new(builtins::BuiltinsHandler));
233        handlers.insert(Opcode::ObjStarts, Box::new(builtins::BuiltinsHandler));
234        handlers.insert(Opcode::ObjEnds, Box::new(builtins::BuiltinsHandler));
235        handlers.insert(Opcode::ObjPos, Box::new(builtins::BuiltinsHandler));
236        handlers.insert(Opcode::ObjCharAt, Box::new(builtins::BuiltinsHandler));
237        handlers.insert(Opcode::ObjLength, Box::new(builtins::BuiltinsHandler));
238        handlers.insert(Opcode::ObjLink, Box::new(builtins::BuiltinsHandler));
239        handlers.insert(Opcode::ObjTrim, Box::new(builtins::BuiltinsHandler));
240        handlers.insert(Opcode::ObjSize, Box::new(builtins::BuiltinsHandler));
241        handlers.insert(Opcode::ObjIndex, Box::new(builtins::BuiltinsHandler));
242        handlers.insert(Opcode::ObjPositions, Box::new(builtins::BuiltinsHandler));
243        handlers.insert(Opcode::ObjAddString, Box::new(builtins::BuiltinsHandler));
244        handlers.insert(Opcode::ObjRemoveString, Box::new(builtins::BuiltinsHandler));
245        handlers.insert(Opcode::ObjDeleteString, Box::new(builtins::BuiltinsHandler));
246        handlers.insert(Opcode::ObjInsertString, Box::new(builtins::BuiltinsHandler));
247        handlers.insert(
248            Opcode::ObjReplaceString,
249            Box::new(builtins::BuiltinsHandler),
250        );
251        handlers.insert(Opcode::ObjSubArray, Box::new(builtins::BuiltinsHandler));
252        handlers.insert(Opcode::ObjType, Box::new(builtins::BuiltinsHandler));
253        handlers.insert(Opcode::ObjClear, Box::new(builtins::BuiltinsHandler));
254
255        // Jump handlers
256        handlers.insert(Opcode::Jne, Box::new(jump::JumpHandler));
257        handlers.insert(Opcode::Jeq, Box::new(jump::JumpHandler));
258        handlers.insert(Opcode::With, Box::new(jump::JumpHandler));
259        handlers.insert(Opcode::ForEach, Box::new(jump::JumpHandler));
260
261        // Short-circuit handlers
262        handlers.insert(
263            Opcode::ShortCircuitAnd,
264            Box::new(short_circuit::ShortCircuitHandler),
265        );
266        handlers.insert(
267            Opcode::ShortCircuitOr,
268            Box::new(short_circuit::ShortCircuitHandler),
269        );
270
271        handlers
272    })
273}