use std::collections::{BTreeMap, BTreeSet};
use crate::decompiler::cfg::BlockId;
use super::super::form::{SsaExpr, SsaForm, SsaStmt, UseSite};
use super::super::variable::SsaVariable;
use super::Subst;
pub(super) fn collect_used(ssa: &SsaForm, _subst: &Subst) -> BTreeSet<SsaVariable> {
let mut used = BTreeSet::new();
for (_bid, block) in ssa.blocks.iter() {
for phi in &block.phi_nodes {
for var in phi.operands.values() {
used.insert(var.clone());
}
}
for stmt in &block.stmts {
if let SsaStmt::Assign { value, .. } = stmt {
used.extend(collect_expr_vars(value));
}
}
}
used
}
pub(super) fn rebuild_indexes(ssa: &mut SsaForm) {
let mut definitions: BTreeMap<SsaVariable, BlockId> = BTreeMap::new();
let mut uses: BTreeMap<SsaVariable, BTreeSet<UseSite>> = BTreeMap::new();
for (bid, block) in ssa.blocks.iter() {
for phi in &block.phi_nodes {
definitions.insert(phi.target.clone(), *bid);
for var in phi.operands.values() {
uses.entry(var.clone())
.or_default()
.insert(UseSite::new(*bid, 0));
}
}
for (i, stmt) in block.stmts.iter().enumerate() {
if let SsaStmt::Assign { target, value } = stmt {
definitions.insert(target.clone(), *bid);
for var in collect_expr_vars(value) {
uses.entry(var).or_default().insert(UseSite::new(*bid, i));
}
}
}
}
ssa.definitions = definitions;
ssa.uses = uses;
}
fn collect_expr_vars(expr: &SsaExpr) -> Vec<SsaVariable> {
let mut out = Vec::new();
collect_expr_vars_into(expr, &mut out);
out
}
fn collect_expr_vars_into(expr: &SsaExpr, out: &mut Vec<SsaVariable>) {
match expr {
SsaExpr::Variable(var) => out.push(var.clone()),
SsaExpr::Binary { left, right, .. } => {
collect_expr_vars_into(left, out);
collect_expr_vars_into(right, out);
}
SsaExpr::Unary { operand, .. } => collect_expr_vars_into(operand, out),
SsaExpr::Call { args, .. } => {
for arg in args {
collect_expr_vars_into(arg, out);
}
}
SsaExpr::Index { base, index } => {
collect_expr_vars_into(base, out);
collect_expr_vars_into(index, out);
}
SsaExpr::Member { base, .. } => collect_expr_vars_into(base, out),
SsaExpr::Cast { expr, .. } => collect_expr_vars_into(expr, out),
SsaExpr::Array(elements) => {
for element in elements {
collect_expr_vars_into(element, out);
}
}
SsaExpr::Map(pairs) => {
for (key, value) in pairs {
collect_expr_vars_into(key, out);
collect_expr_vars_into(value, out);
}
}
SsaExpr::Ternary {
condition,
then_expr,
else_expr,
} => {
collect_expr_vars_into(condition, out);
collect_expr_vars_into(then_expr, out);
collect_expr_vars_into(else_expr, out);
}
SsaExpr::Literal(_) => {}
}
}