Verify that all predecessors to an EBB are valid branches, and have the EBB recorded as a successor.
This commit is contained in:
committed by
Jakob Stoklund Olesen
parent
c596ea1ac1
commit
bb0246c8c1
@@ -72,6 +72,11 @@ impl JumpTableData {
|
|||||||
.enumerate())
|
.enumerate())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if any of the entries branch to `ebb`.
|
||||||
|
pub fn branches_to(&self, ebb: Ebb) -> bool {
|
||||||
|
self.table.iter().any(|target_ebb| target_ebb.expand() == Some(ebb))
|
||||||
|
}
|
||||||
|
|
||||||
/// Access the whole table as a mutable slice.
|
/// Access the whole table as a mutable slice.
|
||||||
pub fn as_mut_slice(&mut self) -> &mut [PackedOption<Ebb>] {
|
pub fn as_mut_slice(&mut self) -> &mut [PackedOption<Ebb>] {
|
||||||
self.table.as_mut_slice()
|
self.table.as_mut_slice()
|
||||||
|
|||||||
@@ -24,9 +24,9 @@
|
|||||||
//!
|
//!
|
||||||
//! Control flow graph and dominator tree integrity:
|
//! Control flow graph and dominator tree integrity:
|
||||||
//!
|
//!
|
||||||
//! TODO:
|
|
||||||
//! - All predecessors in the CFG must be branches to the EBB.
|
//! - All predecessors in the CFG must be branches to the EBB.
|
||||||
//! - All branches to an EBB must be present in the CFG.
|
//! - All branches to an EBB must be present in the CFG.
|
||||||
|
//! TODO:
|
||||||
//! - A recomputed dominator tree is identical to the existing one.
|
//! - A recomputed dominator tree is identical to the existing one.
|
||||||
//!
|
//!
|
||||||
//! Type checking
|
//! Type checking
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
//! of arguments must match the destination type, and the lane indexes must be in range.
|
//! of arguments must match the destination type, and the lane indexes must be in range.
|
||||||
|
|
||||||
use ir::{types, Function, ValueDef, Ebb, Inst, SigRef, FuncRef, ValueList, JumpTable, Value};
|
use ir::{types, Function, ValueDef, Ebb, Inst, SigRef, FuncRef, ValueList, JumpTable, Value};
|
||||||
use ir::instructions::InstructionFormat;
|
use ir::instructions::{InstructionFormat, BranchInfo};
|
||||||
use ir::entities::AnyEntity;
|
use ir::entities::AnyEntity;
|
||||||
use cfg::ControlFlowGraph;
|
use cfg::ControlFlowGraph;
|
||||||
use dominator_tree::DominatorTree;
|
use dominator_tree::DominatorTree;
|
||||||
@@ -342,12 +342,48 @@ impl<'a> Verifier<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cfg_integrity(&self, ebb: Ebb) -> Result<()> {
|
||||||
|
for &(pred_ebb, pred_inst) in self.cfg.get_predecessors(ebb) {
|
||||||
|
// All predecessors in the CFG must be branches to the EBB
|
||||||
|
match self.func.dfg[pred_inst].analyze_branch(&self.func.dfg.value_lists) {
|
||||||
|
BranchInfo::SingleDest(target_ebb, _) => {
|
||||||
|
if target_ebb != ebb {
|
||||||
|
return err!(ebb,
|
||||||
|
"has predecessor {} in {} which does not branch here",
|
||||||
|
pred_inst,
|
||||||
|
pred_ebb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BranchInfo::Table(jt) => {
|
||||||
|
if !self.func.jump_tables[jt].branches_to(ebb) {
|
||||||
|
return err!(ebb,
|
||||||
|
"has predecessor {} using {} in {} which never branches here",
|
||||||
|
pred_inst,
|
||||||
|
jt,
|
||||||
|
pred_ebb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BranchInfo::NotABranch => {
|
||||||
|
return err!(ebb, "has predecessor {} which is not a branch", pred_inst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// All EBBs branching to `ebb` have it recorded as a successor in the CFG.
|
||||||
|
if !self.cfg.get_successors(pred_ebb).contains(&ebb) {
|
||||||
|
return err!(ebb,
|
||||||
|
"predecessor {} does not have this EBB recorded as a successor",
|
||||||
|
pred_ebb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run(&self) -> Result<()> {
|
pub fn run(&self) -> Result<()> {
|
||||||
for ebb in self.func.layout.ebbs() {
|
for ebb in self.func.layout.ebbs() {
|
||||||
for inst in self.func.layout.ebb_insts(ebb) {
|
for inst in self.func.layout.ebb_insts(ebb) {
|
||||||
self.ebb_integrity(ebb, inst)?;
|
self.ebb_integrity(ebb, inst)?;
|
||||||
self.instruction_integrity(inst)?;
|
self.instruction_integrity(inst)?;
|
||||||
}
|
}
|
||||||
|
self.cfg_integrity(ebb)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user