In the verifier, clarify expected versus observed values.

This commit is contained in:
Dan Gohman
2017-11-09 22:02:07 -08:00
parent ced7a88ecc
commit 8dd46054a5

View File

@@ -149,20 +149,20 @@ pub fn verify_context<'a, FOI: Into<FlagsOrIsa<'a>>>(
struct Verifier<'a> { struct Verifier<'a> {
func: &'a Function, func: &'a Function,
cfg: ControlFlowGraph, expected_cfg: ControlFlowGraph,
domtree: DominatorTree, expected_domtree: DominatorTree,
flags: &'a Flags, flags: &'a Flags,
isa: Option<&'a TargetIsa>, isa: Option<&'a TargetIsa>,
} }
impl<'a> Verifier<'a> { impl<'a> Verifier<'a> {
pub fn new(func: &'a Function, fisa: FlagsOrIsa<'a>) -> Verifier<'a> { pub fn new(func: &'a Function, fisa: FlagsOrIsa<'a>) -> Verifier<'a> {
let cfg = ControlFlowGraph::with_function(func); let expected_cfg = ControlFlowGraph::with_function(func);
let domtree = DominatorTree::with_function(func, &cfg); let expected_domtree = DominatorTree::with_function(func, &expected_cfg);
Verifier { Verifier {
func, func,
cfg, expected_cfg,
domtree, expected_domtree,
flags: fisa.flags, flags: fisa.flags,
isa: fisa.isa, isa: fisa.isa,
} }
@@ -461,8 +461,10 @@ impl<'a> Verifier<'a> {
); );
} }
// Defining instruction dominates the instruction that uses the value. // Defining instruction dominates the instruction that uses the value.
if self.domtree.is_reachable(self.func.layout.pp_ebb(loc_inst)) && if self.expected_domtree.is_reachable(
!self.domtree.dominates( self.func.layout.pp_ebb(loc_inst),
) &&
!self.expected_domtree.dominates(
def_inst, def_inst,
loc_inst, loc_inst,
&self.func.layout, &self.func.layout,
@@ -486,8 +488,12 @@ impl<'a> Verifier<'a> {
); );
} }
// The defining EBB dominates the instruction using this value. // The defining EBB dominates the instruction using this value.
if self.domtree.is_reachable(ebb) && if self.expected_domtree.is_reachable(ebb) &&
!self.domtree.dominates(ebb, loc_inst, &self.func.layout) !self.expected_domtree.dominates(
ebb,
loc_inst,
&self.func.layout,
)
{ {
return err!(loc_inst, "uses value arg from non-dominating {}", ebb); return err!(loc_inst, "uses value arg from non-dominating {}", ebb);
} }
@@ -501,8 +507,8 @@ impl<'a> Verifier<'a> {
// dominator for each EBB. Therefore the current domtree is valid if it matches the freshly // dominator for each EBB. Therefore the current domtree is valid if it matches the freshly
// computed one. // computed one.
for ebb in self.func.layout.ebbs() { for ebb in self.func.layout.ebbs() {
let expected = domtree.idom(ebb); let expected = self.expected_domtree.idom(ebb);
let got = self.domtree.idom(ebb); let got = domtree.idom(ebb);
if got != expected { if got != expected {
return err!( return err!(
ebb, ebb,
@@ -514,20 +520,20 @@ impl<'a> Verifier<'a> {
} }
} }
// We also verify if the postorder defined by `DominatorTree` is sane // We also verify if the postorder defined by `DominatorTree` is sane
if self.domtree.cfg_postorder().len() != domtree.cfg_postorder().len() { if domtree.cfg_postorder().len() != self.expected_domtree.cfg_postorder().len() {
return err!( return err!(
AnyEntity::Function, AnyEntity::Function,
"incorrect number of Ebbs in postorder traversal" "incorrect number of Ebbs in postorder traversal"
); );
} }
for (index, (&true_ebb, &test_ebb)) in for (index, (&test_ebb, &true_ebb)) in
self.domtree domtree
.cfg_postorder() .cfg_postorder()
.iter() .iter()
.zip(domtree.cfg_postorder().iter()) .zip(self.expected_domtree.cfg_postorder().iter())
.enumerate() .enumerate()
{ {
if true_ebb != test_ebb { if test_ebb != true_ebb {
return err!( return err!(
test_ebb, test_ebb,
"invalid domtree, postorder ebb number {} should be {}, got {}", "invalid domtree, postorder ebb number {} should be {}, got {}",
@@ -538,8 +544,13 @@ impl<'a> Verifier<'a> {
} }
} }
// We verify rpo_cmp on pairs of adjacent ebbs in the postorder // We verify rpo_cmp on pairs of adjacent ebbs in the postorder
for (&prev_ebb, &next_ebb) in self.domtree.cfg_postorder().iter().adjacent_pairs() { for (&prev_ebb, &next_ebb) in domtree.cfg_postorder().iter().adjacent_pairs() {
if domtree.rpo_cmp(prev_ebb, next_ebb, &self.func.layout) != Ordering::Greater { if self.expected_domtree.rpo_cmp(
prev_ebb,
next_ebb,
&self.func.layout,
) != Ordering::Greater
{
return err!( return err!(
next_ebb, next_ebb,
"invalid domtree, rpo_cmp does not says {} is greater than {}", "invalid domtree, rpo_cmp does not says {} is greater than {}",
@@ -905,7 +916,7 @@ impl<'a> Verifier<'a> {
let mut got_preds = BTreeSet::<Inst>::new(); let mut got_preds = BTreeSet::<Inst>::new();
for ebb in self.func.layout.ebbs() { for ebb in self.func.layout.ebbs() {
expected_succs.extend(self.cfg.get_successors(ebb)); expected_succs.extend(self.expected_cfg.get_successors(ebb));
got_succs.extend(cfg.get_successors(ebb)); got_succs.extend(cfg.get_successors(ebb));
let missing_succs: Vec<Ebb> = expected_succs.difference(&got_succs).cloned().collect(); let missing_succs: Vec<Ebb> = expected_succs.difference(&got_succs).cloned().collect();
@@ -922,7 +933,8 @@ impl<'a> Verifier<'a> {
return err!(ebb, "cfg had unexpected successor(s) {:?}", excess_succs); return err!(ebb, "cfg had unexpected successor(s) {:?}", excess_succs);
} }
expected_preds.extend(self.cfg.get_predecessors(ebb).iter().map(|&(_, inst)| inst)); expected_preds.extend(self.expected_cfg.get_predecessors(ebb).iter().map(|&(_,
inst)| inst));
got_preds.extend(cfg.get_predecessors(ebb).iter().map(|&(_, inst)| inst)); got_preds.extend(cfg.get_predecessors(ebb).iter().map(|&(_, inst)| inst));
let missing_preds: Vec<Inst> = expected_preds.difference(&got_preds).cloned().collect(); let missing_preds: Vec<Inst> = expected_preds.difference(&got_preds).cloned().collect();
@@ -1091,7 +1103,7 @@ impl<'a> Verifier<'a> {
self.verify_return_at_end()?; self.verify_return_at_end()?;
} }
verify_flags(self.func, &self.cfg, self.isa)?; verify_flags(self.func, &self.expected_cfg, self.isa)?;
Ok(()) Ok(())
} }