gbf_core/decompiler/ast/
mod.rs

1#![deny(missing_docs)]
2
3use crate::{decompiler::ast::visitors::AstVisitor, opcode::Opcode};
4use array_access::ArrayAccessNode;
5use array_kind::ArrayKind;
6use assignment::AssignmentNode;
7use bin_op::BinaryOperationNode;
8use block::BlockNode;
9use control_flow::{ControlFlowNode, ControlFlowType};
10use expr::ExprKind;
11use func_call::FunctionCallNode;
12use function::FunctionNode;
13use identifier::IdentifierNode;
14use literal::LiteralNode;
15use member_access::MemberAccessNode;
16use new_array::NewArrayNode;
17use phi::PhiNode;
18use ptr::P;
19use range::RangeNode;
20use ret::ReturnNode;
21use serde::{Deserialize, Serialize};
22use ssa::SsaVersion;
23use statement::StatementKind;
24use thiserror::Error;
25use unary_op::UnaryOperationNode;
26use vbranch::VirtualBranchNode;
27use visitors::{emit_context::EmitContext, emitter::Gs2Emitter};
28
29use super::structure_analysis::region::RegionId;
30
31/// Represents an array access node.
32pub mod array_access;
33/// Represents an array kind
34pub mod array_kind;
35/// Represents an array
36pub mod array_node;
37/// Contains the specifications for any AstNodes that are assignments
38pub mod assignment;
39/// Holds the macro that generates variants for the AST nodes.
40pub mod ast_enum_type;
41/// Represents binary operations in the AST.
42pub mod bin_op;
43/// Represents a "block" of code in the AST.
44pub mod block;
45/// Represents a control flow node in the AST.
46pub mod control_flow;
47/// Contains the specifications for any AstNodes that are expressions
48pub mod expr;
49/// Contains the specifications for any AstNodes that are function calls.
50pub mod func_call;
51/// Contains the specifications for any AstNodes that are functions.
52pub mod function;
53/// Contains the specifications for any AstNodes that are identifiers.
54pub mod identifier;
55/// Contains the specifications for any AstNodes that are literals.
56pub mod literal;
57/// Contains the specifications for any AstNodes that are member accesses.
58pub mod member_access;
59/// Contains the specifications for any AstNodes that are metadata.
60pub mod meta;
61/// Represents the new
62pub mod new;
63/// Represents a new array node in the AST.
64pub mod new_array;
65/// A node identifier
66pub mod node_id;
67/// Represents a phi node in the AST.
68pub mod phi;
69/// Represents an unmerged array
70pub mod phi_array;
71/// Represents a pointer
72pub mod ptr;
73/// Represents a range of values in the AST.
74pub mod range;
75/// Represents a return node in the AST.
76pub mod ret;
77/// Represents SSA versioning for the AST.
78pub mod ssa;
79/// Represents a statement node in the AST.
80pub mod statement;
81/// Represents unary operations in the AST.
82pub mod unary_op;
83/// Represents a virtual branch
84pub mod vbranch;
85/// Represents the visitor pattern for the AST.
86pub mod visitors;
87
88/// Represents an error that occurred while converting an AST node.
89#[derive(Debug, Error, Clone, Serialize, Deserialize)]
90pub enum AstNodeError {
91    /// Invalid conversion from AstNode to another type.
92    #[error("Expected {0}, found {1}")]
93    InvalidConversion(String, String),
94
95    /// Invalid operand for an AST node.
96    #[error("Invalid operand type")]
97    InvalidOperand,
98
99    /// Cannot invert the AST node.
100    #[error("Cannot invert {0}")]
101    CannotInvert(String),
102}
103
104/// Trait for all AST nodes.
105pub trait AstVisitable: Clone {
106    /// Accepts a visitor for the AST node.
107    fn accept<V: AstVisitor>(&self, visitor: &mut V) -> V::Output;
108}
109
110/// Represents an AST node.
111#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
112pub enum AstKind {
113    /// Represents a statement node in the AST, such as `variable = value;`.
114    Statement(StatementKind),
115    /// Represents a function node in the AST.
116    Function(P<FunctionNode>),
117    /// Represents an expression node in the AST.
118    Expression(ExprKind),
119    /// Represenst a block of code in the AST.
120    Block(P<BlockNode>),
121    /// Represents a control flow node in the AST.
122    ControlFlow(P<ControlFlowNode>),
123}
124
125impl AstVisitable for AstKind {
126    fn accept<V: AstVisitor>(&self, visitor: &mut V) -> V::Output {
127        match self {
128            AstKind::Expression(expr) => expr.accept(visitor),
129            AstKind::Statement(stmt) => stmt.accept(visitor),
130            AstKind::Function(func) => func.accept(visitor),
131            AstKind::Block(block) => block.accept(visitor),
132            AstKind::ControlFlow(control_flow) => control_flow.accept(visitor),
133        }
134    }
135}
136
137/// Emits a node into a string.
138pub fn emit<N>(node: N) -> String
139where
140    N: Into<AstKind>,
141{
142    let node: AstKind = node.into();
143    let mut emit = Gs2Emitter::new(EmitContext::default());
144    let ouput = node.accept(&mut emit);
145    ouput.node
146}
147
148// = Assignable expressions =
149
150/// Creates a new AstNode for a statement.
151pub fn new_assignment<L, R>(lhs: L, rhs: R) -> AssignmentNode
152where
153    L: Into<ExprKind>,
154    R: Into<ExprKind>,
155{
156    AssignmentNode {
157        lhs: lhs.into(),
158        rhs: rhs.into(),
159    }
160}
161
162/// Creates a new return node.
163pub fn new_return<N>(node: N) -> ReturnNode
164where
165    N: Into<ExprKind>,
166{
167    ReturnNode::new(node.into())
168}
169
170/// Creates a new virtual branch node.
171pub fn new_virtual_branch(branch: RegionId) -> VirtualBranchNode {
172    VirtualBranchNode::new(branch)
173}
174
175/// Creates a new member access node.
176pub fn new_member_access<L, R>(lhs: L, rhs: R) -> Result<MemberAccessNode, AstNodeError>
177where
178    L: Into<ExprKind>,
179    R: Into<ExprKind>,
180{
181    MemberAccessNode::new(lhs.into(), rhs.into())
182}
183
184// = Expressions =
185
186/// Creates a new AssignableExpr for an identifier
187pub fn new_id(name: &str) -> IdentifierNode {
188    IdentifierNode::new(name)
189}
190
191/// Creates a new AssignableExpr for an identifier with an SSA version.
192pub fn new_id_with_version(name: &str, version: SsaVersion) -> IdentifierNode {
193    IdentifierNode::with_ssa(name, version)
194}
195
196/// Creates a new function call node.
197pub fn new_fn_call_normal<N>(name: N, args: Vec<ExprKind>) -> FunctionCallNode
198where
199    N: Into<ExprKind>,
200{
201    // Create a new array node for the arguments, with name preceding the arguments.
202    let mut args = new_array(args);
203    args.elements.insert(0, name.into());
204    FunctionCallNode::new(args.into())
205}
206
207/// Creates a new function call node, with just the arguments
208pub fn new_fn_call(args: ArrayKind) -> FunctionCallNode {
209    FunctionCallNode::new(args)
210}
211
212/// Creates a new array node.
213pub fn new_array<E>(elements: Vec<E>) -> array_node::ArrayNode
214where
215    E: Into<ExprKind>,
216{
217    array_node::ArrayNode::new(elements.into_iter().map(Into::into).collect())
218}
219
220/// Creates a new phi array node.
221pub fn new_phi_array<E>(phi: P<PhiNode>, elements: Vec<E>) -> phi_array::PhiArrayNode
222where
223    E: Into<ExprKind>,
224{
225    phi_array::PhiArrayNode::new(phi, elements.into_iter().map(Into::into).collect())
226}
227
228/// Creates a new uninitialized array node with a given size.
229pub fn new_uninitialized_array<E>(size: E) -> NewArrayNode
230where
231    E: Into<ExprKind>,
232{
233    NewArrayNode::new(size.into())
234}
235
236/// Creates a new array access node.
237pub fn new_array_access<A, I>(array: A, index: I) -> ArrayAccessNode
238where
239    A: Into<ExprKind>,
240    I: Into<ExprKind>,
241{
242    ArrayAccessNode::new(array.into(), index.into())
243}
244
245/// Creates binary operation node.
246pub fn new_bin_op<L, R>(
247    lhs: L,
248    rhs: R,
249    op_type: bin_op::BinOpType,
250) -> Result<BinaryOperationNode, AstNodeError>
251where
252    L: Into<ExprKind>,
253    R: Into<ExprKind>,
254{
255    BinaryOperationNode::new(lhs.into(), rhs.into(), op_type)
256}
257
258/// Creates a new unary operation node.
259pub fn new_unary_op<A>(
260    operand: A,
261    op_type: unary_op::UnaryOpType,
262) -> Result<UnaryOperationNode, AstNodeError>
263where
264    A: Into<ExprKind>,
265{
266    UnaryOperationNode::new(operand.into(), op_type)
267}
268
269/// Creates a new range node.
270pub fn new_range<L, R>(lhs: L, rhs: R) -> RangeNode
271where
272    L: Into<ExprKind>,
273    R: Into<ExprKind>,
274{
275    RangeNode::new(lhs.into(), rhs.into())
276}
277
278// == Literals ==
279
280/// Creates a new ExprNode for a literal string.
281pub fn new_str(value: &str) -> LiteralNode {
282    LiteralNode::String(value.to_string())
283}
284
285/// Creates a new ExprNode for a literal number.
286pub fn new_num(value: i32) -> LiteralNode {
287    LiteralNode::Number(value)
288}
289
290/// Creates a new ExprNode for a literal float.
291pub fn new_float(value: &str) -> LiteralNode {
292    LiteralNode::Float(value.to_string())
293}
294
295/// Creates a new ExprNode for a literal boolean.
296pub fn new_bool(value: bool) -> LiteralNode {
297    LiteralNode::Boolean(value)
298}
299
300/// Creates a new ExprNode for a literal null.
301pub fn new_null() -> LiteralNode {
302    LiteralNode::Null
303}
304
305// == Functions ==
306/// Creates a new function node.
307pub fn new_fn<V, E>(name: Option<String>, params: Vec<E>, body: Vec<V>) -> FunctionNode
308where
309    V: Into<AstKind>,
310    E: Into<ExprKind>,
311{
312    FunctionNode::new(
313        name,
314        new_array(params).into(),
315        body.into_iter().map(Into::into).collect::<Vec<AstKind>>(),
316    )
317}
318
319// == Conditionals ==
320/// Creates a new if statement
321pub fn new_if<C, E>(condition: C, then_block: Vec<E>) -> ControlFlowNode
322where
323    C: Into<ExprKind>,
324    E: Into<AstKind>,
325{
326    ControlFlowNode::new(
327        ControlFlowType::If,
328        Some(condition),
329        then_block
330            .into_iter()
331            .map(Into::into)
332            .collect::<Vec<AstKind>>(),
333    )
334}
335
336/// Creates a new else statement
337pub fn new_else<T>(else_block: Vec<T>) -> ControlFlowNode
338where
339    T: Into<AstKind>,
340{
341    ControlFlowNode::new(
342        ControlFlowType::Else,
343        None::<ExprKind>,
344        else_block
345            .into_iter()
346            .map(Into::into)
347            .collect::<Vec<AstKind>>(),
348    )
349}
350
351/// Creates a new with statement
352pub fn new_with<C, T>(condition: C, then_block: Vec<T>) -> ControlFlowNode
353where
354    C: Into<ExprKind>,
355    T: Into<AstKind>,
356{
357    ControlFlowNode::new(
358        ControlFlowType::With,
359        Some(condition),
360        then_block
361            .into_iter()
362            .map(Into::into)
363            .collect::<Vec<AstKind>>(),
364    )
365}
366
367// == Phi Nodes ==
368/// Creates a new unresolved phi node.
369pub fn new_phi(idx: usize) -> phi::PhiNode {
370    PhiNode::new(idx)
371}
372
373/// Creates a new while loop
374pub fn new_while<C, T>(condition: C, then_block: Vec<T>) -> ControlFlowNode
375where
376    C: Into<ExprKind>,
377    T: Into<AstKind>,
378{
379    ControlFlowNode::new(
380        ControlFlowType::While,
381        Some(condition),
382        then_block
383            .into_iter()
384            .map(Into::into)
385            .collect::<Vec<AstKind>>(),
386    )
387}
388
389// TODO: There is a bug right now where the condition is improperly flipped for do-whiles.
390/// Creates a new do while loop
391pub fn new_do_while<C, T>(condition: C, then_block: Vec<T>) -> ControlFlowNode
392where
393    C: Into<ExprKind>,
394    T: Into<AstKind>,
395{
396    ControlFlowNode::new(
397        ControlFlowType::DoWhile,
398        Some(condition),
399        then_block
400            .into_iter()
401            .map(Into::into)
402            .collect::<Vec<AstKind>>(),
403    )
404}
405
406/// Creates a new for loop
407pub fn new_for<C, T>(condition: C, then_block: Vec<T>) -> ControlFlowNode
408where
409    C: Into<ExprKind>,
410    T: Into<AstKind>,
411{
412    ControlFlowNode::new(
413        ControlFlowType::For,
414        Some(condition),
415        then_block
416            .into_iter()
417            .map(Into::into)
418            .collect::<Vec<AstKind>>(),
419    )
420}
421
422/// Creates a new cyclic condition
423pub fn new_cyclic_condition<C, T>(
424    condition: C,
425    then_block: Vec<T>,
426    opcode: Option<Opcode>,
427) -> Result<ControlFlowNode, AstNodeError>
428where
429    C: Into<ExprKind>,
430    T: Into<AstKind>,
431{
432    match opcode {
433        Some(Opcode::Jne) => Ok(new_while(condition, then_block)),
434        // TODO: Move condition flipping logic here for Jeq
435        Some(Opcode::Jeq) => Ok(new_while(condition, then_block)),
436        // TODO: We may need to flip the condition on ShortCircuitAnd or ShortCircuitOr
437        Some(Opcode::ShortCircuitAnd) => Ok(new_while(condition, then_block)),
438        Some(Opcode::ShortCircuitOr) => Ok(new_while(condition, then_block)),
439        Some(Opcode::ForEach) => Ok(new_for(condition, then_block)),
440        None => Ok(new_while(condition, then_block)),
441        _ => Err(AstNodeError::InvalidOperand),
442    }
443}
444
445/// Creates a new acyclic condition
446pub fn new_acylic_condition<C, T>(
447    condition: C,
448    then_block: Vec<T>,
449    opcode: Option<Opcode>,
450) -> Result<ControlFlowNode, AstNodeError>
451where
452    C: Into<ExprKind>,
453    T: Into<AstKind>,
454{
455    match opcode {
456        Some(Opcode::Jne) => Ok(new_if(
457            condition,
458            then_block
459                .into_iter()
460                .map(Into::into)
461                .collect::<Vec<AstKind>>(),
462        )),
463        // TODO: Move condition flipping logic here for Jeq
464        Some(Opcode::Jeq) => Ok(new_if(condition, then_block)),
465        // TODO: We may need to flip the condition on ShortCircuitAnd or ShortCircuitOr
466        Some(Opcode::ShortCircuitAnd) => Ok(new_if(condition, then_block)),
467        Some(Opcode::ShortCircuitOr) => Ok(new_if(condition, then_block)),
468        Some(Opcode::With) => Ok(new_with(condition, then_block)),
469        None => Ok(new_if(condition, then_block)),
470        _ => Err(AstNodeError::InvalidOperand),
471    }
472}
473
474/// Creates a new new node.
475pub fn new_new<N>(new_type: N, arg: N) -> Result<new::NewNode, AstNodeError>
476where
477    N: Into<ExprKind>,
478{
479    new::NewNode::new(new_type.into(), arg.into())
480}