gbf_core/decompiler/ast/
ssa.rs

1#![deny(missing_docs)]
2use std::{cmp::Ordering, collections::HashMap, fmt::Display, ops::AddAssign};
3
4use serde::{Deserialize, Serialize};
5
6/// Represents the SSA version of a variable.
7#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Copy)]
8pub struct SsaVersion(usize);
9
10/// Context for the SSA transformation.
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct SsaContext {
13    /// The current versions of variables.
14    pub current_versions: HashMap<String, SsaVersion>,
15    /// The next version to assign.
16    pub next_version: SsaVersion,
17}
18
19impl SsaContext {
20    /// Creates a new `SsaContext`.
21    pub fn new() -> Self {
22        Self {
23            current_versions: HashMap::new(),
24            next_version: 0.into(),
25        }
26    }
27
28    /// Creates a new SSA version for the given variable.
29    pub fn new_ssa_version_for(&mut self, location: &str) -> SsaVersion {
30        let version = self.next_version;
31        self.next_version += 1;
32
33        self.current_versions.insert(location.to_string(), version);
34        version
35    }
36
37    /// Returns the current version of the given variable.
38    pub fn current_version_of(&self, location: &str) -> Option<SsaVersion> {
39        self.current_versions.get(location).copied()
40    }
41
42    /// Returns the current version of the given variable, or creates a new one if it doesn't exist.
43    pub fn current_version_of_or_new(&mut self, location: &str) -> SsaVersion {
44        self.current_versions
45            .get(location)
46            .copied()
47            .unwrap_or_else(|| self.new_ssa_version_for(location))
48    }
49}
50
51// == Other implementations ==
52impl AddAssign for SsaVersion {
53    fn add_assign(&mut self, rhs: Self) {
54        self.0 += rhs.0;
55    }
56}
57
58impl AddAssign<usize> for SsaVersion {
59    fn add_assign(&mut self, rhs: usize) {
60        self.0 += rhs;
61    }
62}
63
64impl From<SsaVersion> for usize {
65    fn from(value: SsaVersion) -> Self {
66        value.0
67    }
68}
69
70impl From<usize> for SsaVersion {
71    fn from(value: usize) -> Self {
72        SsaVersion(value)
73    }
74}
75
76impl PartialOrd for SsaVersion {
77    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
78        Some(self.0.cmp(&other.0))
79    }
80}
81
82impl Ord for SsaVersion {
83    fn cmp(&self, other: &Self) -> Ordering {
84        self.0.cmp(&other.0)
85    }
86}
87
88impl Display for SsaVersion {
89    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90        write!(f, "{}", self.0)
91    }
92}
93
94impl Default for SsaContext {
95    fn default() -> Self {
96        Self::new()
97    }
98}