gbf_core/decompiler/
function_decompiler_context.rs1#![deny(missing_docs)]
2
3use crate::basic_block::BasicBlockId;
4use crate::instruction::Instruction;
5use crate::opcode::Opcode;
6use std::backtrace::Backtrace;
7use std::collections::HashMap;
8
9use super::ast::array_kind::ArrayKind;
10use super::ast::array_node::ArrayNode;
11use super::ast::expr::ExprKind;
12use super::ast::identifier::IdentifierNode;
13use super::ast::phi::PhiNode;
14use super::ast::phi_array::PhiArrayNode;
15use super::ast::ptr::P;
16use super::ast::ssa::SsaContext;
17use super::ast::{AstKind, new_phi};
18use super::execution_frame::ExecutionFrame;
19use super::function_decompiler::{FunctionDecompilerError, FunctionDecompilerErrorContext};
20use super::handlers::{OpcodeHandler, global_opcode_handlers};
21use super::{ProcessedInstruction, ProcessedInstructionBuilder};
22
23pub struct FunctionDecompilerContext {
25 pub block_ast_node_stack: HashMap<BasicBlockId, Vec<ExecutionFrame>>,
27 pub block_ast_phi_count: HashMap<BasicBlockId, usize>,
29 pub current_block_id: BasicBlockId,
31 pub opcode_handlers: HashMap<Opcode, Box<dyn OpcodeHandler>>,
33 pub ssa_context: SsaContext,
35 pub current_instruction: Instruction,
37 pub register_mapping: HashMap<usize, ExprKind>,
39}
40
41impl FunctionDecompilerContext {
42 pub fn new(start_block_id: BasicBlockId) -> Self {
44 Self {
45 block_ast_node_stack: HashMap::new(),
46 current_block_id: start_block_id,
47 opcode_handlers: HashMap::new(),
48 ssa_context: SsaContext::new(),
49 current_instruction: Instruction::default(),
50 register_mapping: HashMap::new(),
51 block_ast_phi_count: HashMap::new(),
52 }
53 }
54
55 pub fn start_block_processing(
64 &mut self,
65 block_id: BasicBlockId,
66 ) -> Result<(), FunctionDecompilerError> {
67 self.current_block_id = block_id;
68 self.block_ast_node_stack.insert(block_id, Vec::new());
69 Ok(())
70 }
71
72 pub fn process_instruction(
80 &mut self,
81 instr: &Instruction,
82 ) -> Result<ProcessedInstruction, FunctionDecompilerError> {
83 self.current_instruction = instr.clone();
84
85 let current_block_id = self.current_block_id;
86
87 if instr.opcode == Opcode::PushArray {
89 let stack = self
90 .block_ast_node_stack
91 .get_mut(¤t_block_id)
92 .expect("Critical error: stack should always be set for each basic block");
93
94 stack.push(ExecutionFrame::BuildingArray(Vec::new()));
95 return Ok(ProcessedInstructionBuilder::new().build());
96 }
97 if instr.opcode == Opcode::Swap {
99 let error_context = self.get_error_context();
100
101 let last = {
102 let stack = self
103 .block_ast_node_stack
104 .get_mut(¤t_block_id)
105 .expect("Critical error: stack should always be set for each basic block");
106 stack.pop()
107 }
108 .unwrap_or_else(|| {
109 ExecutionFrame::StandaloneNode(AstKind::Expression(self.new_phi().into()))
110 });
111
112 let second_last = {
113 let stack = self
114 .block_ast_node_stack
115 .get_mut(¤t_block_id)
116 .expect("Critical error: stack should always be set for each basic block");
117 stack.pop()
118 }
119 .unwrap_or_else(|| {
120 ExecutionFrame::StandaloneNode(AstKind::Expression(self.new_phi().into()))
121 });
122
123 let stack = self
124 .block_ast_node_stack
125 .get_mut(¤t_block_id)
126 .expect("Critical error: stack should always be set for each basic block");
127
128 match last {
132 ExecutionFrame::BuildingArray(mut last_array) => match second_last {
133 ExecutionFrame::BuildingArray(mut second_last_array) => {
134 last_array.append(&mut second_last_array);
135 stack.push(ExecutionFrame::BuildingArray(last_array));
136 }
137 ExecutionFrame::StandaloneNode(n) => {
138 let expr = match n {
140 AstKind::Expression(e) => e,
141 _ => {
142 return Err(FunctionDecompilerError::UnexpectedNodeType {
143 expected: "Expression".to_string(),
144 context: error_context,
145 backtrace: Backtrace::capture(),
146 });
147 }
148 };
149 last_array.push(expr);
150 stack.push(ExecutionFrame::BuildingArray(last_array));
151 }
152 },
153 _ => {
154 stack.push(last);
155 stack.push(second_last);
156 }
157 }
158
159 return Ok(ProcessedInstructionBuilder::new().build());
160 }
161
162 let handlers = global_opcode_handlers();
163
164 let handler =
165 handlers
166 .get(&instr.opcode)
167 .ok_or(FunctionDecompilerError::UnimplementedOpcode {
168 opcode: instr.opcode,
169 context: self.get_error_context(),
170 backtrace: Backtrace::capture(),
171 })?;
172
173 let op = handler.handle_instruction(self, instr)?;
177
178 if let Some(ssa_id) = &op.ssa_id {
180 self.push_one_node(ssa_id.clone().into())?;
181 }
182
183 Ok(op)
184 }
185
186 pub fn get_error_context(&self) -> Box<FunctionDecompilerErrorContext> {
188 Box::new(FunctionDecompilerErrorContext {
189 current_block_id: self.current_block_id,
190 current_instruction: self.current_instruction.clone(),
191 current_ast_node_stack: self
192 .block_ast_node_stack
193 .get(&self.current_block_id)
194 .unwrap_or(&Vec::new())
195 .to_vec(),
196 })
197 }
198
199 pub fn get_stack(&self, block_id: &BasicBlockId) -> Option<&Vec<ExecutionFrame>> {
201 self.block_ast_node_stack.get(block_id)
202 }
203
204 pub fn new_phi(&mut self) -> PhiNode {
206 let block_id = self.current_block_id;
207 let phi_count = *self.block_ast_phi_count.entry(block_id).or_insert(0);
208 let phi = new_phi(phi_count);
209 self.block_ast_phi_count.insert(block_id, phi_count + 1);
210 phi
211 }
212
213 pub fn pop_building_array(&mut self) -> Result<ArrayKind, FunctionDecompilerError> {
220 let block_id = self.current_block_id;
221 let frame_opt = {
222 let stack = self
224 .block_ast_node_stack
225 .get_mut(&block_id)
226 .expect("Critical error: stack should always be set for each basic block");
227 stack.pop()
228 };
229
230 match frame_opt {
231 None => {
233 let phi = self.new_phi();
234 Ok(ArrayKind::PhiArray(
235 PhiArrayNode::new(phi.into(), Vec::new()).into(),
236 ))
237 }
238 Some(frame) => match frame {
239 ExecutionFrame::BuildingArray(array) => {
240 let rev: Vec<ExprKind> = array.into_iter().rev().collect();
242 Ok(ArrayKind::MergedArray(ArrayNode::new(rev).into()))
243 }
244 ExecutionFrame::StandaloneNode(node) => {
245 let node = match node {
247 AstKind::Expression(e) => e,
248 _ => {
249 return Err(FunctionDecompilerError::UnexpectedNodeType {
250 expected: "Expression".to_string(),
251 context: self.get_error_context(),
252 backtrace: Backtrace::capture(),
253 });
254 }
255 };
256 let mut nodes: Vec<ExprKind> = vec![node];
261
262 {
264 let stack = self.block_ast_node_stack.get_mut(&block_id).expect(
265 "Critical error: stack should always be set for each basic block",
266 );
267 while let Some(frame) = stack.pop() {
268 match frame {
269 ExecutionFrame::StandaloneNode(n) => {
270 let expr = match n {
272 AstKind::Expression(e) => e,
273 _ => {
274 return Err(
275 FunctionDecompilerError::UnexpectedNodeType {
276 expected: "Expression".to_string(),
277 context: self.get_error_context(),
278 backtrace: Backtrace::capture(),
279 },
280 );
281 }
282 };
283 nodes.push(expr);
284 }
285 ExecutionFrame::BuildingArray(_) => {
286 return Err(FunctionDecompilerError::UnexpectedNodeType {
287 expected: "StandaloneNode".to_string(),
288 context: self.get_error_context(),
289 backtrace: Backtrace::capture(),
290 });
291 }
292 }
293 }
294 }
295
296 let phi = self.new_phi();
298 Ok(ArrayKind::PhiArray(
299 PhiArrayNode::new(phi.into(), nodes).into(),
300 ))
301 }
302 },
303 }
304 }
305
306 pub fn pop_one_node(&mut self) -> Result<AstKind, FunctionDecompilerError> {
308 let block_id = self.current_block_id;
309 let frame_opt = {
310 let stack = self
311 .block_ast_node_stack
312 .get_mut(&block_id)
313 .expect("Critical error: stack should always be set for each basic block");
314 stack.pop()
315 };
316
317 let mut last_frame = match frame_opt {
319 Some(frame) => frame,
320 None => return Ok(AstKind::Expression(self.new_phi().into())),
321 };
322
323 let result = match &mut last_frame {
324 ExecutionFrame::BuildingArray(array) => {
325 if let Some(node) = array.pop() {
327 Ok(AstKind::Expression(node))
328 } else {
329 Ok(AstKind::Expression(self.new_phi().into()))
330 }
331 }
332 ExecutionFrame::StandaloneNode(node) => Ok(node.clone()),
333 };
334
335 if let ExecutionFrame::BuildingArray(_) = last_frame {
337 let stack = self
338 .block_ast_node_stack
339 .get_mut(&block_id)
340 .expect("Critical error: stack should always be set for each basic block");
341 stack.push(last_frame);
342 }
343
344 result
345 }
346
347 pub fn pop_expression(&mut self) -> Result<ExprKind, FunctionDecompilerError> {
349 let node = self.pop_one_node()?;
350 match node {
351 AstKind::Expression(expr) => Ok(expr.clone()),
352 _ => Err(FunctionDecompilerError::UnexpectedNodeType {
353 expected: "Expression".to_string(),
354 context: self.get_error_context(),
355 backtrace: Backtrace::capture(),
356 }),
357 }
358 }
359
360 pub fn pop_identifier(&mut self) -> Result<P<IdentifierNode>, FunctionDecompilerError> {
362 let node = self.pop_expression()?;
363
364 match node {
365 ExprKind::Identifier(ident) => Ok(ident.clone()),
366 _ => Err(FunctionDecompilerError::UnexpectedNodeType {
367 expected: "Identifier".to_string(),
368 context: self.get_error_context(),
369 backtrace: Backtrace::capture(),
370 }),
371 }
372 }
373
374 pub fn push_one_node(&mut self, node: AstKind) -> Result<(), FunctionDecompilerError> {
376 let block_id = self.current_block_id;
377
378 let stack = self
379 .block_ast_node_stack
380 .get_mut(&block_id)
381 .expect("Critical error: stack should always be set for each basic block");
382
383 if let Some(last_frame) = stack.last_mut() {
385 match last_frame {
386 ExecutionFrame::BuildingArray(array) => {
387 if let AstKind::Expression(expr) = node {
389 array.push(expr.clone());
390 return Ok(());
391 } else {
392 return Err(FunctionDecompilerError::UnexpectedNodeType {
393 expected: "Expression".to_string(),
394 context: self.get_error_context(),
395 backtrace: Backtrace::capture(),
396 });
397 }
398 }
399 ExecutionFrame::StandaloneNode(_) => {
400 }
402 }
403 }
404
405 stack.push(ExecutionFrame::StandaloneNode(node));
407 Ok(())
408 }
409}