coverage: Let each coverage statement hold a vector of code regions
This makes it possible for a `StatementKind::Coverage` to hold more than one code region, but that capability is not yet used.
This commit is contained in:
parent
1355e1fc74
commit
ee9d00f6b8
9 changed files with 96 additions and 90 deletions
|
@ -11,7 +11,7 @@ pub struct Expression {
|
||||||
lhs: Operand,
|
lhs: Operand,
|
||||||
op: Op,
|
op: Op,
|
||||||
rhs: Operand,
|
rhs: Operand,
|
||||||
region: Option<CodeRegion>,
|
code_regions: Vec<CodeRegion>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Collects all of the coverage regions associated with (a) injected counters, (b) counter
|
/// Collects all of the coverage regions associated with (a) injected counters, (b) counter
|
||||||
|
@ -30,7 +30,7 @@ pub struct FunctionCoverage<'tcx> {
|
||||||
instance: Instance<'tcx>,
|
instance: Instance<'tcx>,
|
||||||
source_hash: u64,
|
source_hash: u64,
|
||||||
is_used: bool,
|
is_used: bool,
|
||||||
counters: IndexVec<CounterId, Option<CodeRegion>>,
|
counters: IndexVec<CounterId, Option<Vec<CodeRegion>>>,
|
||||||
expressions: IndexVec<ExpressionId, Option<Expression>>,
|
expressions: IndexVec<ExpressionId, Option<Expression>>,
|
||||||
unreachable_regions: Vec<CodeRegion>,
|
unreachable_regions: Vec<CodeRegion>,
|
||||||
}
|
}
|
||||||
|
@ -77,28 +77,40 @@ impl<'tcx> FunctionCoverage<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a code region to be counted by an injected counter intrinsic.
|
/// Adds code regions to be counted by an injected counter intrinsic.
|
||||||
pub fn add_counter(&mut self, id: CounterId, region: CodeRegion) {
|
#[instrument(level = "debug", skip(self))]
|
||||||
if let Some(previous_region) = self.counters[id].replace(region.clone()) {
|
pub(crate) fn add_counter(&mut self, id: CounterId, code_regions: &[CodeRegion]) {
|
||||||
assert_eq!(previous_region, region, "add_counter: code region for id changed");
|
if code_regions.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let slot = &mut self.counters[id];
|
||||||
|
match slot {
|
||||||
|
None => *slot = Some(code_regions.to_owned()),
|
||||||
|
// If this counter ID slot has already been filled, it should
|
||||||
|
// contain identical information.
|
||||||
|
Some(ref previous_regions) => assert_eq!(
|
||||||
|
previous_regions, code_regions,
|
||||||
|
"add_counter: code regions for id changed"
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds information about a coverage expression, along with zero or more
|
||||||
|
/// code regions mapped to that expression.
|
||||||
|
///
|
||||||
/// Both counters and "counter expressions" (or simply, "expressions") can be operands in other
|
/// Both counters and "counter expressions" (or simply, "expressions") can be operands in other
|
||||||
/// expressions. These are tracked as separate variants of `Operand`, so there is no ambiguity
|
/// expressions. These are tracked as separate variants of `Operand`, so there is no ambiguity
|
||||||
/// between operands that are counter IDs and operands that are expression IDs.
|
/// between operands that are counter IDs and operands that are expression IDs.
|
||||||
pub fn add_counter_expression(
|
#[instrument(level = "debug", skip(self))]
|
||||||
|
pub(crate) fn add_counter_expression(
|
||||||
&mut self,
|
&mut self,
|
||||||
expression_id: ExpressionId,
|
expression_id: ExpressionId,
|
||||||
lhs: Operand,
|
lhs: Operand,
|
||||||
op: Op,
|
op: Op,
|
||||||
rhs: Operand,
|
rhs: Operand,
|
||||||
region: Option<CodeRegion>,
|
code_regions: &[CodeRegion],
|
||||||
) {
|
) {
|
||||||
debug!(
|
|
||||||
"add_counter_expression({:?}, lhs={:?}, op={:?}, rhs={:?} at {:?}",
|
|
||||||
expression_id, lhs, op, rhs, region
|
|
||||||
);
|
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
expression_id.as_usize() < self.expressions.len(),
|
expression_id.as_usize() < self.expressions.len(),
|
||||||
"expression_id {} is out of range for expressions.len() = {}
|
"expression_id {} is out of range for expressions.len() = {}
|
||||||
|
@ -107,23 +119,25 @@ impl<'tcx> FunctionCoverage<'tcx> {
|
||||||
self.expressions.len(),
|
self.expressions.len(),
|
||||||
self,
|
self,
|
||||||
);
|
);
|
||||||
if let Some(previous_expression) = self.expressions[expression_id].replace(Expression {
|
|
||||||
lhs,
|
let expression = Expression { lhs, op, rhs, code_regions: code_regions.to_owned() };
|
||||||
op,
|
let slot = &mut self.expressions[expression_id];
|
||||||
rhs,
|
match slot {
|
||||||
region: region.clone(),
|
None => *slot = Some(expression),
|
||||||
}) {
|
// If this expression ID slot has already been filled, it should
|
||||||
assert_eq!(
|
// contain identical information.
|
||||||
previous_expression,
|
Some(ref previous_expression) => assert_eq!(
|
||||||
Expression { lhs, op, rhs, region },
|
previous_expression, &expression,
|
||||||
"add_counter_expression: expression for id changed"
|
"add_counter_expression: expression for id changed"
|
||||||
);
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a region that will be marked as "unreachable", with a constant "zero counter".
|
/// Adds regions that will be marked as "unreachable", with a constant "zero counter".
|
||||||
pub fn add_unreachable_region(&mut self, region: CodeRegion) {
|
#[instrument(level = "debug", skip(self))]
|
||||||
self.unreachable_regions.push(region)
|
pub(crate) fn add_unreachable_regions(&mut self, code_regions: &[CodeRegion]) {
|
||||||
|
assert!(!code_regions.is_empty(), "unreachable regions always have code regions");
|
||||||
|
self.unreachable_regions.extend_from_slice(code_regions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform some simplifications to make the final coverage mappings
|
/// Perform some simplifications to make the final coverage mappings
|
||||||
|
@ -212,10 +226,15 @@ impl<'tcx> FunctionCoverage<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn counter_regions(&self) -> impl Iterator<Item = (Counter, &CodeRegion)> {
|
fn counter_regions(&self) -> impl Iterator<Item = (Counter, &CodeRegion)> {
|
||||||
self.counters.iter_enumerated().filter_map(|(index, entry)| {
|
self.counters
|
||||||
// Option::map() will return None to filter out missing counters. This may happen
|
.iter_enumerated()
|
||||||
// if, for example, a MIR-instrumented counter is removed during an optimization.
|
// Filter out counter IDs that we never saw during MIR traversal.
|
||||||
entry.as_ref().map(|region| (Counter::counter_value_reference(index), region))
|
// This can happen if a counter was optimized out by MIR transforms
|
||||||
|
// (and replaced with `CoverageKind::Unreachable` instead).
|
||||||
|
.filter_map(|(id, maybe_code_regions)| Some((id, maybe_code_regions.as_ref()?)))
|
||||||
|
.flat_map(|(id, code_regions)| {
|
||||||
|
let counter = Counter::counter_value_reference(id);
|
||||||
|
code_regions.iter().map(move |region| (counter, region))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,13 +273,17 @@ impl<'tcx> FunctionCoverage<'tcx> {
|
||||||
|
|
||||||
fn expression_regions(&self) -> Vec<(Counter, &CodeRegion)> {
|
fn expression_regions(&self) -> Vec<(Counter, &CodeRegion)> {
|
||||||
// Find all of the expression IDs that weren't optimized out AND have
|
// Find all of the expression IDs that weren't optimized out AND have
|
||||||
// an attached code region, and return the corresponding mapping as a
|
// one or more attached code regions, and return the corresponding
|
||||||
// counter/region pair.
|
// mappings as counter/region pairs.
|
||||||
self.expressions
|
self.expressions
|
||||||
.iter_enumerated()
|
.iter_enumerated()
|
||||||
.filter_map(|(id, expression)| {
|
.filter_map(|(id, maybe_expression)| {
|
||||||
let code_region = expression.as_ref()?.region.as_ref()?;
|
let code_regions = &maybe_expression.as_ref()?.code_regions;
|
||||||
Some((Counter::expression(id), code_region))
|
Some((id, code_regions))
|
||||||
|
})
|
||||||
|
.flat_map(|(id, code_regions)| {
|
||||||
|
let counter = Counter::expression(id);
|
||||||
|
code_regions.iter().map(move |code_region| (counter, code_region))
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,25 +108,15 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
|
||||||
.entry(instance)
|
.entry(instance)
|
||||||
.or_insert_with(|| FunctionCoverage::new(bx.tcx(), instance));
|
.or_insert_with(|| FunctionCoverage::new(bx.tcx(), instance));
|
||||||
|
|
||||||
let Coverage { kind, code_region } = coverage.clone();
|
let Coverage { kind, code_regions } = coverage;
|
||||||
match kind {
|
match *kind {
|
||||||
CoverageKind::Counter { function_source_hash, id } => {
|
CoverageKind::Counter { function_source_hash, id } => {
|
||||||
debug!(
|
debug!(
|
||||||
"ensuring function source hash is set for instance={:?}; function_source_hash={}",
|
"ensuring function source hash is set for instance={:?}; function_source_hash={}",
|
||||||
instance, function_source_hash,
|
instance, function_source_hash,
|
||||||
);
|
);
|
||||||
func_coverage.set_function_source_hash(function_source_hash);
|
func_coverage.set_function_source_hash(function_source_hash);
|
||||||
|
func_coverage.add_counter(id, code_regions);
|
||||||
if let Some(code_region) = code_region {
|
|
||||||
// Note: Some counters do not have code regions, but may still be referenced
|
|
||||||
// from expressions. In that case, don't add the counter to the coverage map,
|
|
||||||
// but do inject the counter intrinsic.
|
|
||||||
debug!(
|
|
||||||
"adding counter to coverage_map: instance={:?}, id={:?}, region={:?}",
|
|
||||||
instance, id, code_region,
|
|
||||||
);
|
|
||||||
func_coverage.add_counter(id, code_region);
|
|
||||||
}
|
|
||||||
// We need to explicitly drop the `RefMut` before calling into `instrprof_increment`,
|
// We need to explicitly drop the `RefMut` before calling into `instrprof_increment`,
|
||||||
// as that needs an exclusive borrow.
|
// as that needs an exclusive borrow.
|
||||||
drop(coverage_map);
|
drop(coverage_map);
|
||||||
|
@ -144,20 +134,10 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
|
||||||
bx.instrprof_increment(fn_name, hash, num_counters, index);
|
bx.instrprof_increment(fn_name, hash, num_counters, index);
|
||||||
}
|
}
|
||||||
CoverageKind::Expression { id, lhs, op, rhs } => {
|
CoverageKind::Expression { id, lhs, op, rhs } => {
|
||||||
debug!(
|
func_coverage.add_counter_expression(id, lhs, op, rhs, code_regions);
|
||||||
"adding counter expression to coverage_map: instance={:?}, id={:?}, {:?} {:?} {:?}; region: {:?}",
|
|
||||||
instance, id, lhs, op, rhs, code_region,
|
|
||||||
);
|
|
||||||
func_coverage.add_counter_expression(id, lhs, op, rhs, code_region);
|
|
||||||
}
|
}
|
||||||
CoverageKind::Unreachable => {
|
CoverageKind::Unreachable => {
|
||||||
let code_region =
|
func_coverage.add_unreachable_regions(code_regions);
|
||||||
code_region.expect("unreachable regions always have code regions");
|
|
||||||
debug!(
|
|
||||||
"adding unreachable code to coverage_map: instance={:?}, at {:?}",
|
|
||||||
instance, code_region,
|
|
||||||
);
|
|
||||||
func_coverage.add_unreachable_region(code_region);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,7 +206,8 @@ fn add_unused_function_coverage<'tcx>(
|
||||||
|
|
||||||
let mut function_coverage = FunctionCoverage::unused(tcx, instance);
|
let mut function_coverage = FunctionCoverage::unused(tcx, instance);
|
||||||
for &code_region in tcx.covered_code_regions(def_id) {
|
for &code_region in tcx.covered_code_regions(def_id) {
|
||||||
function_coverage.add_unreachable_region(code_region.clone());
|
let code_region = std::slice::from_ref(code_region);
|
||||||
|
function_coverage.add_unreachable_regions(code_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(coverage_context) = cx.coverage_context() {
|
if let Some(coverage_context) = cx.coverage_context() {
|
||||||
|
|
|
@ -16,7 +16,7 @@ use rustc_middle::mir::interpret::{
|
||||||
Pointer, Provenance,
|
Pointer, Provenance,
|
||||||
};
|
};
|
||||||
use rustc_middle::mir::visit::Visitor;
|
use rustc_middle::mir::visit::Visitor;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::{self, *};
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_target::abi::Size;
|
use rustc_target::abi::Size;
|
||||||
|
|
||||||
|
@ -685,10 +685,13 @@ impl Debug for Statement<'_> {
|
||||||
AscribeUserType(box (ref place, ref c_ty), ref variance) => {
|
AscribeUserType(box (ref place, ref c_ty), ref variance) => {
|
||||||
write!(fmt, "AscribeUserType({place:?}, {variance:?}, {c_ty:?})")
|
write!(fmt, "AscribeUserType({place:?}, {variance:?}, {c_ty:?})")
|
||||||
}
|
}
|
||||||
Coverage(box self::Coverage { ref kind, code_region: Some(ref rgn) }) => {
|
Coverage(box mir::Coverage { ref kind, ref code_regions }) => {
|
||||||
write!(fmt, "Coverage::{kind:?} for {rgn:?}")
|
if code_regions.is_empty() {
|
||||||
|
write!(fmt, "Coverage::{kind:?}")
|
||||||
|
} else {
|
||||||
|
write!(fmt, "Coverage::{kind:?} for {code_regions:?}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Coverage(box ref coverage) => write!(fmt, "Coverage::{:?}", coverage.kind),
|
|
||||||
Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"),
|
Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"),
|
||||||
ConstEvalCounter => write!(fmt, "ConstEvalCounter"),
|
ConstEvalCounter => write!(fmt, "ConstEvalCounter"),
|
||||||
Nop => write!(fmt, "nop"),
|
Nop => write!(fmt, "nop"),
|
||||||
|
|
|
@ -514,7 +514,7 @@ pub enum FakeReadCause {
|
||||||
#[derive(TypeFoldable, TypeVisitable)]
|
#[derive(TypeFoldable, TypeVisitable)]
|
||||||
pub struct Coverage {
|
pub struct Coverage {
|
||||||
pub kind: CoverageKind,
|
pub kind: CoverageKind,
|
||||||
pub code_region: Option<CodeRegion>,
|
pub code_regions: Vec<CodeRegion>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
|
#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
|
||||||
|
|
|
@ -243,7 +243,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
||||||
self.mir_body,
|
self.mir_body,
|
||||||
self.make_mir_coverage_kind(&counter_kind),
|
self.make_mir_coverage_kind(&counter_kind),
|
||||||
self.bcb_leader_bb(bcb),
|
self.bcb_leader_bb(bcb),
|
||||||
Some(code_region),
|
vec![code_region],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,7 +302,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
||||||
self.mir_body,
|
self.mir_body,
|
||||||
self.make_mir_coverage_kind(&counter_kind),
|
self.make_mir_coverage_kind(&counter_kind),
|
||||||
inject_to_bb,
|
inject_to_bb,
|
||||||
None,
|
Vec::new(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
BcbCounter::Expression { .. } => inject_intermediate_expression(
|
BcbCounter::Expression { .. } => inject_intermediate_expression(
|
||||||
|
@ -367,20 +367,14 @@ fn inject_statement(
|
||||||
mir_body: &mut mir::Body<'_>,
|
mir_body: &mut mir::Body<'_>,
|
||||||
counter_kind: CoverageKind,
|
counter_kind: CoverageKind,
|
||||||
bb: BasicBlock,
|
bb: BasicBlock,
|
||||||
some_code_region: Option<CodeRegion>,
|
code_regions: Vec<CodeRegion>,
|
||||||
) {
|
) {
|
||||||
debug!(
|
debug!(" injecting statement {counter_kind:?} for {bb:?} at code regions: {code_regions:?}");
|
||||||
" injecting statement {:?} for {:?} at code region: {:?}",
|
|
||||||
counter_kind, bb, some_code_region
|
|
||||||
);
|
|
||||||
let data = &mut mir_body[bb];
|
let data = &mut mir_body[bb];
|
||||||
let source_info = data.terminator().source_info;
|
let source_info = data.terminator().source_info;
|
||||||
let statement = Statement {
|
let statement = Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Coverage(Box::new(Coverage {
|
kind: StatementKind::Coverage(Box::new(Coverage { kind: counter_kind, code_regions })),
|
||||||
kind: counter_kind,
|
|
||||||
code_region: some_code_region,
|
|
||||||
})),
|
|
||||||
};
|
};
|
||||||
data.statements.insert(0, statement);
|
data.statements.insert(0, statement);
|
||||||
}
|
}
|
||||||
|
@ -394,7 +388,10 @@ fn inject_intermediate_expression(mir_body: &mut mir::Body<'_>, expression: Cove
|
||||||
let source_info = data.terminator().source_info;
|
let source_info = data.terminator().source_info;
|
||||||
let statement = Statement {
|
let statement = Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Coverage(Box::new(Coverage { kind: expression, code_region: None })),
|
kind: StatementKind::Coverage(Box::new(Coverage {
|
||||||
|
kind: expression,
|
||||||
|
code_regions: Vec::new(),
|
||||||
|
})),
|
||||||
};
|
};
|
||||||
data.statements.push(statement);
|
data.statements.push(statement);
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,8 +93,8 @@ fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) ->
|
||||||
fn covered_code_regions(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<&CodeRegion> {
|
fn covered_code_regions(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<&CodeRegion> {
|
||||||
let body = mir_body(tcx, def_id);
|
let body = mir_body(tcx, def_id);
|
||||||
all_coverage_in_mir_body(body)
|
all_coverage_in_mir_body(body)
|
||||||
// Not all coverage statements have an attached code region.
|
// Coverage statements have a list of code regions (possibly empty).
|
||||||
.filter_map(|coverage| coverage.code_region.as_ref())
|
.flat_map(|coverage| coverage.code_regions.as_slice())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -441,21 +441,23 @@ fn save_unreachable_coverage(
|
||||||
let dead_block = &basic_blocks[dead_block];
|
let dead_block = &basic_blocks[dead_block];
|
||||||
for statement in &dead_block.statements {
|
for statement in &dead_block.statements {
|
||||||
let StatementKind::Coverage(coverage) = &statement.kind else { continue };
|
let StatementKind::Coverage(coverage) = &statement.kind else { continue };
|
||||||
let Some(code_region) = &coverage.code_region else { continue };
|
if coverage.code_regions.is_empty() {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
let instance = statement.source_info.scope.inlined_instance(source_scopes);
|
let instance = statement.source_info.scope.inlined_instance(source_scopes);
|
||||||
if live.contains(&instance) {
|
if live.contains(&instance) {
|
||||||
retained_coverage.push((statement.source_info, code_region.clone()));
|
retained_coverage.push((statement.source_info, coverage.code_regions.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let start_block = &mut basic_blocks[START_BLOCK];
|
let start_block = &mut basic_blocks[START_BLOCK];
|
||||||
start_block.statements.extend(retained_coverage.into_iter().map(
|
start_block.statements.extend(retained_coverage.into_iter().map(
|
||||||
|(source_info, code_region)| Statement {
|
|(source_info, code_regions)| Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Coverage(Box::new(Coverage {
|
kind: StatementKind::Coverage(Box::new(Coverage {
|
||||||
kind: CoverageKind::Unreachable,
|
kind: CoverageKind::Unreachable,
|
||||||
code_region: Some(code_region),
|
code_regions,
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
let mut _0: bool;
|
let mut _0: bool;
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
+ Coverage::Counter(0) for /the/src/instrument_coverage.rs:20:1 - 22:2;
|
+ Coverage::Counter(0) for [/the/src/instrument_coverage.rs:20:1 - 22:2];
|
||||||
_0 = const true;
|
_0 = const true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,12 @@
|
||||||
let mut _3: !;
|
let mut _3: !;
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
+ Coverage::Counter(0) for /the/src/instrument_coverage.rs:11:1 - 11:11;
|
+ Coverage::Counter(0) for [/the/src/instrument_coverage.rs:11:1 - 11:11];
|
||||||
goto -> bb1;
|
goto -> bb1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
+ Coverage::Expression(0) = Counter(0) + Counter(1) for /the/src/instrument_coverage.rs:12:5 - 13:17;
|
+ Coverage::Expression(0) = Counter(0) + Counter(1) for [/the/src/instrument_coverage.rs:12:5 - 13:17];
|
||||||
falseUnwind -> [real: bb2, unwind: bb6];
|
falseUnwind -> [real: bb2, unwind: bb6];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,15 +27,15 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
+ Coverage::Expression(2) = Expression(1) + Zero for /the/src/instrument_coverage.rs:17:1 - 17:2;
|
+ Coverage::Expression(2) = Expression(1) + Zero for [/the/src/instrument_coverage.rs:17:1 - 17:2];
|
||||||
+ Coverage::Expression(1) = Expression(0) - Counter(1) for /the/src/instrument_coverage.rs:14:13 - 14:18;
|
+ Coverage::Expression(1) = Expression(0) - Counter(1) for [/the/src/instrument_coverage.rs:14:13 - 14:18];
|
||||||
_0 = const ();
|
_0 = const ();
|
||||||
StorageDead(_2);
|
StorageDead(_2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
bb5: {
|
||||||
+ Coverage::Counter(1) for /the/src/instrument_coverage.rs:15:10 - 15:11;
|
+ Coverage::Counter(1) for [/the/src/instrument_coverage.rs:15:10 - 15:11];
|
||||||
_1 = const ();
|
_1 = const ();
|
||||||
StorageDead(_2);
|
StorageDead(_2);
|
||||||
goto -> bb1;
|
goto -> bb1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue