nyx/src/ssa/mod.rs
Eli Peter 1f2bfe76c1
docs: Enhance module documentation across various files for clarity a… (#62)
* docs: Enhance module documentation across various files for clarity and completeness

* fix: Remove unnecessary blank line in build.rs for cleaner code

* docs: Update documentation to improve clarity and consistency in code comments
2026-05-02 17:46:45 -04:00

123 lines
4.6 KiB
Rust

//! SSA IR, lowering, and optimization passes.
//!
//! The pipeline converts a CFG into a pruned SSA body consumed by the taint
//! analysis engine. [`lower_to_ssa`] inserts phi nodes via Cytron's algorithm
//! and renames variables along the dominator tree. [`optimize_ssa`] runs
//! constant propagation, branch pruning, copy propagation, DCE, and type
//! fact analysis in sequence.
//!
//! Key submodules:
//! - [`ir`]: core types (`SsaValue`, `SsaOp`, `SsaInst`, `SsaBlock`, `SsaBody`)
//! - [`lower`]: CFG-to-SSA lowering with Cytron phi insertion and dominator-tree rename
//! - [`const_prop`]: sparse conditional constant propagation with branch pruning
//! - [`copy_prop`]: copy and alias propagation
//! - [`dce`]: dead definition elimination
//! - [`type_facts`]: per-value type inference (`TypeKind`, `TypeFactResult`)
//! - [`heap`]: abstract heap for container element abstractions
//! - [`alias`]: base-variable alias groups from copy propagation
#[allow(dead_code)] // IR types, fields used by Display impl, tests, and downstream analyses
pub mod alias;
pub mod const_prop;
pub mod copy_prop;
pub mod dce;
pub mod display;
pub mod heap;
pub mod invariants;
#[allow(dead_code)]
pub mod ir;
pub mod lower;
pub mod param_points_to;
pub mod pointsto;
pub mod static_map;
pub mod type_facts;
#[allow(unused_imports)]
pub use ir::*;
pub use lower::lower_to_ssa;
pub use lower::lower_to_ssa_scoped_nop;
pub use lower::lower_to_ssa_with_params;
use crate::cfg::Cfg;
use crate::ssa::type_facts::TypeKind;
use crate::symbol::Lang;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// Result of SSA optimization passes.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OptimizeResult {
/// Per-SSA-value constant lattice values.
pub const_values: HashMap<SsaValue, const_prop::ConstLattice>,
/// Type fact analysis results.
pub type_facts: type_facts::TypeFactResult,
/// Base-variable alias groups from copy propagation.
pub alias_result: alias::BaseAliasResult,
/// Points-to analysis: per-SSA-value abstract heap object sets.
pub points_to: heap::PointsToResult,
/// Module aliases from `require()` calls: SSA value → possible module names.
/// Used to resolve dynamic dispatch like `lib.request()` where `lib = require("http")`.
pub module_aliases: HashMap<SsaValue, smallvec::SmallVec<[String; 2]>>,
/// Number of branches pruned by constant propagation.
pub branches_pruned: usize,
/// Number of copies eliminated.
pub copies_eliminated: usize,
/// Number of dead definitions removed.
pub dead_defs_removed: usize,
}
/// Run all SSA optimization passes on a body.
///
/// Pipeline: const propagation → branch pruning → copy propagation → DCE → type facts.
pub fn optimize_ssa(body: &mut SsaBody, cfg: &Cfg, lang: Option<Lang>) -> OptimizeResult {
optimize_ssa_with_param_types(body, cfg, lang, &[])
}
/// Same as [`optimize_ssa`] but seeds [`SsaOp::Param`] values with
/// per-position [`TypeKind`] facts derived from the function's
/// `BodyMeta.param_types`. Strictly additive: an empty slice or
/// `None` entries leave the type-fact analysis behaviour unchanged.
pub fn optimize_ssa_with_param_types(
body: &mut SsaBody,
cfg: &Cfg,
lang: Option<Lang>,
param_types: &[Option<TypeKind>],
) -> OptimizeResult {
// 1. Constant propagation (SCCP)
let cp = const_prop::const_propagate(body);
let branches_pruned = const_prop::apply_const_prop(body, &cp);
// 2. Copy propagation
let (copies_eliminated, copy_map) = copy_prop::copy_propagate(body, cfg);
// 3. Alias analysis (uses copy_map before DCE removes dead defs)
let alias_result = alias::compute_base_aliases(&copy_map, body);
// 4. Dead code elimination
let dead_defs_removed = dce::eliminate_dead_defs(body, cfg);
// 5. Type fact analysis (uses const prop results + language for constructor inference)
let type_facts =
type_facts::analyze_types_with_param_types(body, cfg, &cp.values, lang, param_types);
// 6. Points-to analysis (uses allocation site detection + SSA def-use)
let points_to = heap::analyze_points_to(body, cfg, lang);
// 7. Module alias analysis (require() tracking for JS/TS)
let module_aliases = if matches!(lang, Some(Lang::JavaScript) | Some(Lang::TypeScript)) {
const_prop::collect_module_aliases(body, &cp.values)
} else {
HashMap::new()
};
OptimizeResult {
const_values: cp.values,
type_facts,
alias_result,
points_to,
module_aliases,
branches_pruned,
copies_eliminated,
dead_defs_removed,
}
}