mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
coverage: Make CoverageSuccessors
a struct
This commit is contained in:
parent
75eff9a574
commit
8834b5ad51
@ -1,7 +1,7 @@
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::iter;
|
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
|
use std::{iter, slice};
|
||||||
|
|
||||||
use rustc_data_structures::captures::Captures;
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
@ -389,34 +389,26 @@ impl BasicCoverageBlockData {
|
|||||||
/// indicates whether that block can potentially be combined into the same BCB
|
/// indicates whether that block can potentially be combined into the same BCB
|
||||||
/// as its sole successor.
|
/// as its sole successor.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
enum CoverageSuccessors<'a> {
|
struct CoverageSuccessors<'a> {
|
||||||
/// The terminator has exactly one straight-line successor, so its block can
|
/// Coverage-relevant successors of the corresponding terminator.
|
||||||
/// potentially be combined into the same BCB as that successor.
|
/// There might be 0, 1, or multiple targets.
|
||||||
Chainable(BasicBlock),
|
targets: &'a [BasicBlock],
|
||||||
/// The block cannot be combined into the same BCB as its successor(s).
|
/// `Yield` terminators are not chainable, because their sole out-edge is
|
||||||
NotChainable(&'a [BasicBlock]),
|
/// only followed if/when the generator is resumed after the yield.
|
||||||
/// Yield terminators are not chainable, and their execution count can also
|
is_yield: bool,
|
||||||
/// differ from the execution count of their out-edge.
|
|
||||||
Yield(BasicBlock),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CoverageSuccessors<'_> {
|
impl CoverageSuccessors<'_> {
|
||||||
fn is_chainable(&self) -> bool {
|
fn is_chainable(&self) -> bool {
|
||||||
match self {
|
// If a terminator is out-summable and has exactly one out-edge, then
|
||||||
Self::Chainable(_) => true,
|
// it is eligible to be chained into its successor block.
|
||||||
Self::NotChainable(_) => false,
|
self.is_out_summable() && self.targets.len() == 1
|
||||||
Self::Yield(_) => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the terminator itself is assumed to have the same
|
/// Returns true if the terminator itself is assumed to have the same
|
||||||
/// execution count as the sum of its out-edges (assuming no panics).
|
/// execution count as the sum of its out-edges (assuming no panics).
|
||||||
fn is_out_summable(&self) -> bool {
|
fn is_out_summable(&self) -> bool {
|
||||||
match self {
|
!self.is_yield && !self.targets.is_empty()
|
||||||
Self::Chainable(_) => true,
|
|
||||||
Self::NotChainable(_) => true,
|
|
||||||
Self::Yield(_) => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,12 +417,7 @@ impl IntoIterator for CoverageSuccessors<'_> {
|
|||||||
type IntoIter = impl DoubleEndedIterator<Item = Self::Item>;
|
type IntoIter = impl DoubleEndedIterator<Item = Self::Item>;
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
match self {
|
self.targets.iter().copied()
|
||||||
Self::Chainable(bb) | Self::Yield(bb) => {
|
|
||||||
Some(bb).into_iter().chain((&[]).iter().copied())
|
|
||||||
}
|
|
||||||
Self::NotChainable(bbs) => None.into_iter().chain(bbs.iter().copied()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,14 +427,17 @@ impl IntoIterator for CoverageSuccessors<'_> {
|
|||||||
// `catch_unwind()` handlers.
|
// `catch_unwind()` handlers.
|
||||||
fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> CoverageSuccessors<'a> {
|
fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> CoverageSuccessors<'a> {
|
||||||
use TerminatorKind::*;
|
use TerminatorKind::*;
|
||||||
match terminator.kind {
|
let mut is_yield = false;
|
||||||
|
let targets = match &terminator.kind {
|
||||||
// A switch terminator can have many coverage-relevant successors.
|
// A switch terminator can have many coverage-relevant successors.
|
||||||
// (If there is exactly one successor, we still treat it as not chainable.)
|
SwitchInt { targets, .. } => targets.all_targets(),
|
||||||
SwitchInt { ref targets, .. } => CoverageSuccessors::NotChainable(targets.all_targets()),
|
|
||||||
|
|
||||||
// A yield terminator has exactly 1 successor, but should not be chained,
|
// A yield terminator has exactly 1 successor, but should not be chained,
|
||||||
// because its resume edge has a different execution count.
|
// because its resume edge has a different execution count.
|
||||||
Yield { resume, .. } => CoverageSuccessors::Yield(resume),
|
Yield { resume, .. } => {
|
||||||
|
is_yield = true;
|
||||||
|
slice::from_ref(resume)
|
||||||
|
}
|
||||||
|
|
||||||
// These terminators have exactly one coverage-relevant successor,
|
// These terminators have exactly one coverage-relevant successor,
|
||||||
// and can be chained into it.
|
// and can be chained into it.
|
||||||
@ -455,24 +445,15 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera
|
|||||||
| Drop { target, .. }
|
| Drop { target, .. }
|
||||||
| FalseEdge { real_target: target, .. }
|
| FalseEdge { real_target: target, .. }
|
||||||
| FalseUnwind { real_target: target, .. }
|
| FalseUnwind { real_target: target, .. }
|
||||||
| Goto { target } => CoverageSuccessors::Chainable(target),
|
| Goto { target } => slice::from_ref(target),
|
||||||
|
|
||||||
// A call terminator can normally be chained, except when it has no
|
// A call terminator can normally be chained, except when it has no
|
||||||
// successor because it is known to diverge.
|
// successor because it is known to diverge.
|
||||||
Call { target: maybe_target, .. } => match maybe_target {
|
Call { target: maybe_target, .. } => maybe_target.as_slice(),
|
||||||
Some(target) => CoverageSuccessors::Chainable(target),
|
|
||||||
None => CoverageSuccessors::NotChainable(&[]),
|
|
||||||
},
|
|
||||||
|
|
||||||
// An inline asm terminator can normally be chained, except when it
|
// An inline asm terminator can normally be chained, except when it
|
||||||
// diverges or uses asm goto.
|
// diverges or uses asm goto.
|
||||||
InlineAsm { ref targets, .. } => {
|
InlineAsm { targets, .. } => &targets,
|
||||||
if let [target] = targets[..] {
|
|
||||||
CoverageSuccessors::Chainable(target)
|
|
||||||
} else {
|
|
||||||
CoverageSuccessors::NotChainable(targets)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// These terminators have no coverage-relevant successors.
|
// These terminators have no coverage-relevant successors.
|
||||||
CoroutineDrop
|
CoroutineDrop
|
||||||
@ -480,8 +461,10 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera
|
|||||||
| TailCall { .. }
|
| TailCall { .. }
|
||||||
| Unreachable
|
| Unreachable
|
||||||
| UnwindResume
|
| UnwindResume
|
||||||
| UnwindTerminate(_) => CoverageSuccessors::NotChainable(&[]),
|
| UnwindTerminate(_) => &[],
|
||||||
}
|
};
|
||||||
|
|
||||||
|
CoverageSuccessors { targets, is_yield }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maintains separate worklists for each loop in the BasicCoverageBlock CFG, plus one for the
|
/// Maintains separate worklists for each loop in the BasicCoverageBlock CFG, plus one for the
|
||||||
|
Loading…
Reference in New Issue
Block a user