//! SSA validation. use crate::cfg::CFGInfo; use crate::entity::*; use crate::ir::*; struct DefBlocks { def_block: PerEntity<Value, Block>, } impl DefBlocks { fn compute(body: &FunctionBody) -> Self { let mut def_block = PerEntity::default(); for (block, data) in body.blocks.entries() { for &(_, param) in &data.params { def_block[param] = block; } for &inst in &data.insts { def_block[inst] = block; } } DefBlocks { def_block } } } pub fn run(body: &FunctionBody, cfg: &CFGInfo) { let def_blocks = DefBlocks::compute(body); for (block, data) in body.blocks.entries() { let validate = |value| { let value = body.resolve_alias(value); let def_block = def_blocks.def_block[value]; assert!(cfg.dominates(def_block, block)); }; for &inst in &data.insts { match &body.values[inst] { &ValueDef::Operator(_, ref args, _) => { for &arg in args { validate(arg); } } &ValueDef::PickOutput(val, _, _) => { validate(val); } &ValueDef::Trace(_, ref args) => { for &arg in args { validate(arg); } } &ValueDef::Alias(..) => {} &ValueDef::None | &ValueDef::Placeholder(_) | &ValueDef::BlockParam(..) => {} } } data.terminator.visit_uses(|u| validate(u)); } }