pub mod algebraic;
pub mod blockmerge;
pub mod controlflow;
pub mod copying;
pub mod deadcode;
pub mod gvn;
pub mod licm;
pub mod loopcanon;
pub mod predicates;
pub mod ranges;
pub mod reassociate;
mod scheduling;
pub mod strength;
pub mod threading;
pub mod utils;
pub use predicates::PredicateResult;
pub use scheduling::{
AlgebraicSimplificationPass, BlockMergingPass, ControlFlowSimplificationPass,
CopyPropagationPass, DeadCodeEliminationPass, DeadMethodEliminationPass,
GlobalValueNumberingPass, JumpThreadingPass, LicmPass, LoopCanonicalizationPass,
OpaquePredicatePass, ReassociationPass, StrengthReductionPass, ValueRangePropagationPass,
};
#[cfg(test)]
mod tests {
use std::{fs, path::Path};
#[test]
fn pass_implementations_do_not_bypass_editor_api() {
let pass_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("src/passes");
let forbidden = [
"ssa.replace_uses_checked(",
"ssa.propagate_copies(",
"ssa.nop_copy_defining(",
"ssa.replace_instruction_op(",
"ssa.remove_instruction(",
"ssa.repair_ssa(",
"ssa.rebuild_ssa(",
"ssa.strip_nops(",
"ssa.compact_variables(",
"ssa.block_mut(",
"ssa.blocks_mut(",
"ssa.variables_mut(",
];
let mut violations = Vec::new();
for entry in fs::read_dir(&pass_dir).expect("read pass source directory") {
let entry = entry.expect("read pass source entry");
let path = entry.path();
if path.extension().and_then(|ext| ext.to_str()) != Some("rs") {
continue;
}
let source = fs::read_to_string(&path).expect("read pass source file");
let production = source.split("#[cfg(test)]").next().unwrap_or(&source);
for (line_idx, line) in production.lines().enumerate() {
for pattern in forbidden {
if line.contains(pattern) {
violations.push(format!(
"{}:{} uses {pattern}",
path.display(),
line_idx + 1
));
}
}
}
}
assert!(
violations.is_empty(),
"SSA passes must mutate through SsaFunction::edit/SsaEditor only:\n{}",
violations.join("\n")
);
}
}