|
| 1 | +use std::collections::HashSet; |
| 2 | +use crate::ir::{ir::*, lowerer::TempId}; |
| 3 | + |
| 4 | +pub fn verify_ir(ir: &ProgramIR) { |
| 5 | + for func in &ir.functions { |
| 6 | + let mut verifier = FunctionIRVerifier { ir: func, defined: HashSet::new() }; |
| 7 | + verifier.verify_entry_exists(); |
| 8 | + for block in &func.blocks { |
| 9 | + verifier.verify_block(block); |
| 10 | + } |
| 11 | + } |
| 12 | +} |
| 13 | + |
| 14 | +struct FunctionIRVerifier<'a> { |
| 15 | + ir: &'a FunctionIR, |
| 16 | + defined: HashSet<TempId>, |
| 17 | +} |
| 18 | + |
| 19 | +impl FunctionIRVerifier<'_> { |
| 20 | + fn verify_entry_exists(&self) { |
| 21 | + self.ir.blocks.len() > 0; |
| 22 | + } |
| 23 | + |
| 24 | + fn verify_temp(&self, id: TempId) { |
| 25 | + self.defined.contains(&id); |
| 26 | + } |
| 27 | + |
| 28 | + fn verify_temp_def(&mut self, id: TempId) { |
| 29 | + self.ir.temps.len() > id.index(); |
| 30 | + self.defined.insert(id); |
| 31 | + } |
| 32 | + |
| 33 | + fn verify_instr(&mut self, instr: &Instr) { |
| 34 | + match instr { |
| 35 | + Instr::LoadConst { dst, .. } => { |
| 36 | + self.verify_temp_def(*dst) |
| 37 | + } |
| 38 | + Instr::Binary { dst, lhs, rhs, .. } { |
| 39 | + self.verify_temp(*lhs); |
| 40 | + self.verify_temp(*rhs); |
| 41 | + self.verify_temp_def(*dst); |
| 42 | + } |
| 43 | + Instr::Store { place, value } => { |
| 44 | + match value { |
| 45 | + Value::Temp(*id) => self.verify_temp(*id), |
| 46 | + _ => {} |
| 47 | + } |
| 48 | + |
| 49 | + match place { |
| 50 | + Place::Local(id) => self.ir.locals.len() > id.index(), |
| 51 | + }; |
| 52 | + } |
| 53 | + Instr::Load { dst, place } => { |
| 54 | + match place { |
| 55 | + Place::Local(id) => self.ir.locals.len() > id.index(), |
| 56 | + }; |
| 57 | + self.verify_temp_def(dst) |
| 58 | + } |
| 59 | + Instr::Poision { dst } => { |
| 60 | + if let Some(id) = dst { |
| 61 | + self.verify_temp_def(*id) |
| 62 | + } |
| 63 | + } |
| 64 | + } |
| 65 | + } |
| 66 | + |
| 67 | + fn verify_terminator(&self, term: &Terminator) { |
| 68 | + match term { |
| 69 | + Goto(id) => { self.ir.blocks.len() > id.len(); }, |
| 70 | + Return(Value::Temp(id)) => self.verify_temp(*id), |
| 71 | + _ => {} |
| 72 | + } |
| 73 | + } |
| 74 | + |
| 75 | + fn verify_block(&mut self, block: &Block) { |
| 76 | + for instr in &block.instrs { |
| 77 | + self.verify_instr(instr); |
| 78 | + } |
| 79 | + self.verify_terminator(&block.terminator) |
| 80 | + } |
| 81 | +} |
| 82 | + |
0 commit comments