gbf_core/decompiler/handlers/
literal.rs1#![deny(missing_docs)]
2
3use std::backtrace::Backtrace;
4
5use crate::{
6 decompiler::{
7 ProcessedInstruction, ProcessedInstructionBuilder,
8 ast::{
9 new_assignment, new_bool, new_float, new_id_with_version, new_null, new_num, new_str,
10 },
11 function_decompiler::FunctionDecompilerError,
12 function_decompiler_context::FunctionDecompilerContext,
13 },
14 instruction::Instruction,
15 opcode::Opcode,
16 operand::Operand,
17};
18
19use super::OpcodeHandler;
20
21pub struct LiteralHandler;
23
24impl OpcodeHandler for LiteralHandler {
25 fn handle_instruction(
26 &self,
27 context: &mut FunctionDecompilerContext,
28 instruction: &Instruction,
29 ) -> Result<ProcessedInstruction, FunctionDecompilerError> {
30 let literal = if instruction.opcode == Opcode::PushTrue
32 || instruction.opcode == Opcode::PushFalse
33 {
34 new_bool(instruction.opcode == Opcode::PushTrue)
35 } else if instruction.opcode == Opcode::PushNull {
36 new_null()
37 } else {
38 let operand = instruction.operand.as_ref().ok_or(
40 FunctionDecompilerError::InstructionMustHaveOperand {
41 opcode: instruction.opcode,
42 context: context.get_error_context(),
43 backtrace: Backtrace::capture(),
44 },
45 )?;
46
47 match instruction.opcode {
48 Opcode::PushString => new_str(operand.get_string_value().map_err(|e| {
49 FunctionDecompilerError::OperandError {
50 source: e,
51 context: context.get_error_context(),
52 backtrace: Backtrace::capture(),
53 }
54 })?),
55 Opcode::PushNumber => match operand {
56 Operand::Float(_) => new_float(operand.get_string_value().map_err(|e| {
57 FunctionDecompilerError::OperandError {
58 source: e,
59 context: context.get_error_context(),
60 backtrace: Backtrace::capture(),
61 }
62 })?),
63 Operand::Number(_) => new_num(operand.get_number_value().map_err(|e| {
64 FunctionDecompilerError::OperandError {
65 source: e,
66 context: context.get_error_context(),
67 backtrace: Backtrace::capture(),
68 }
69 })?),
70 _ => {
71 return Err(FunctionDecompilerError::Other {
72 message: format!("Invalid operand type for PushNumber: {:?}", operand),
73 context: context.get_error_context(),
74 backtrace: Backtrace::capture(),
75 });
76 }
77 },
78 _ => {
79 return Err(FunctionDecompilerError::UnimplementedOpcode {
80 opcode: instruction.opcode,
81 context: context.get_error_context(),
82 backtrace: Backtrace::capture(),
83 });
84 }
85 }
86 };
87
88 let ver = context.ssa_context.new_ssa_version_for("lit");
89 let ssa_id = new_id_with_version("lit", ver);
90 let stmt = new_assignment(ssa_id.clone(), literal);
91
92 Ok(ProcessedInstructionBuilder::new()
93 .push_to_region(stmt.into())
94 .ssa_id(ssa_id.into())
95 .build())
96 }
99}