Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d55f927

Browse files
committedAug 3, 2020
Completes support for coverage in external crates
The prior PR corrected for errors encountered when trying to generate the coverage map on source code inlined from external crates (including macros and generics) by avoiding adding external DefIds to the coverage map. This made it possible to generate a coverage report including external crates, but the external crate coverage was incomplete (did not include coverage for the DefIds that were eliminated. The root issue was that the coverage map was converting Span locations to source file and locations, using the SourceMap for the current crate, and this would not work for spans from external crates (compliled with a different SourceMap). The solution was to convert the Spans to filename and location during MIR generation instead, so precompiled external crates would already have the correct source code locations embedded in their MIR, when imported into another crate.
1 parent 5ef872f commit d55f927

File tree

14 files changed

+352
-325
lines changed

14 files changed

+352
-325
lines changed
 

‎library/core/src/intrinsics.rs

+27-9
Original file line numberDiff line numberDiff line change
@@ -1950,15 +1950,20 @@ extern "rust-intrinsic" {
19501950
pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
19511951

19521952
/// Internal placeholder for injecting code coverage counters when the "instrument-coverage"
1953-
/// option is enabled. The placeholder is replaced with `llvm.instrprof.increment` during code
1954-
/// generation.
1953+
/// option is enabled. The source code region information is extracted prior to code generation,
1954+
/// and added to the "coverage map", which is injected into the generated code as additional
1955+
/// data. This intrinsic then triggers the generation of LLVM intrinsic call
1956+
/// `instrprof.increment`, using the remaining args (`function_source_hash` and `index`).
19551957
#[cfg(not(bootstrap))]
19561958
#[lang = "count_code_region"]
19571959
pub fn count_code_region(
19581960
function_source_hash: u64,
19591961
index: u32,
1960-
start_byte_pos: u32,
1961-
end_byte_pos: u32,
1962+
file_name: &'static str,
1963+
start_line: u32,
1964+
start_col: u32,
1965+
end_line: u32,
1966+
end_col: u32,
19621967
);
19631968

19641969
/// Internal marker for code coverage expressions, injected into the MIR when the
@@ -1973,8 +1978,11 @@ extern "rust-intrinsic" {
19731978
index: u32,
19741979
left_index: u32,
19751980
right_index: u32,
1976-
start_byte_pos: u32,
1977-
end_byte_pos: u32,
1981+
file_name: &'static str,
1982+
start_line: u32,
1983+
start_col: u32,
1984+
end_line: u32,
1985+
end_col: u32,
19781986
);
19791987

19801988
/// This marker identifies a code region and two other counters or counter expressions
@@ -1986,14 +1994,24 @@ extern "rust-intrinsic" {
19861994
index: u32,
19871995
left_index: u32,
19881996
right_index: u32,
1989-
start_byte_pos: u32,
1990-
end_byte_pos: u32,
1997+
file_name: &'static str,
1998+
start_line: u32,
1999+
start_col: u32,
2000+
end_line: u32,
2001+
end_col: u32,
19912002
);
19922003

19932004
/// This marker identifies a code region to be added to the "coverage map" to indicate source
19942005
/// code that can never be reached.
19952006
/// (See `coverage_counter_add` for more information.)
1996-
pub fn coverage_unreachable(start_byte_pos: u32, end_byte_pos: u32);
2007+
#[cfg(not(bootstrap))]
2008+
pub fn coverage_unreachable(
2009+
file_name: &'static str,
2010+
start_line: u32,
2011+
start_col: u32,
2012+
end_line: u32,
2013+
end_col: u32,
2014+
);
19972015

19982016
/// See documentation of `<*const T>::guaranteed_eq` for details.
19992017
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]

‎src/librustc_codegen_llvm/coverageinfo/mapgen.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ impl CoverageMapGenerator {
9292
fn write_coverage_mappings(
9393
&mut self,
9494
expressions: Vec<CounterExpression>,
95-
counter_regions: impl Iterator<Item = (Counter, &'a Region)>,
95+
counter_regions: impl Iterator<Item = (Counter, &'tcx Region<'tcx>)>,
9696
coverage_mappings_buffer: &RustString,
9797
) {
9898
let mut counter_regions = counter_regions.collect::<Vec<_>>();
@@ -102,7 +102,7 @@ impl CoverageMapGenerator {
102102

103103
let mut virtual_file_mapping = Vec::new();
104104
let mut mapping_regions = Vec::new();
105-
let mut current_file_path = None;
105+
let mut current_file_name = None;
106106
let mut current_file_id = 0;
107107

108108
// Convert the list of (Counter, Region) pairs to an array of `CounterMappingRegion`, sorted
@@ -112,22 +112,22 @@ impl CoverageMapGenerator {
112112
// `filenames` array.
113113
counter_regions.sort_unstable_by_key(|(_counter, region)| *region);
114114
for (counter, region) in counter_regions {
115-
let (file_path, start_line, start_col, end_line, end_col) = region.file_start_and_end();
116-
let same_file = current_file_path.as_ref().map_or(false, |p| p == file_path);
115+
let Region { file_name, start_line, start_col, end_line, end_col } = *region;
116+
let same_file = current_file_name.as_ref().map_or(false, |p| p == file_name);
117117
if !same_file {
118-
if current_file_path.is_some() {
118+
if current_file_name.is_some() {
119119
current_file_id += 1;
120120
}
121-
current_file_path = Some(file_path.clone());
122-
let filename = CString::new(file_path.to_string_lossy().to_string())
123-
.expect("null error converting filename to C string");
124-
debug!(" file_id: {} = '{:?}'", current_file_id, filename);
125-
let filenames_index = match self.filename_to_index.get(&filename) {
121+
current_file_name = Some(file_name.to_string());
122+
let c_filename =
123+
CString::new(file_name).expect("null error converting filename to C string");
124+
debug!(" file_id: {} = '{:?}'", current_file_id, c_filename);
125+
let filenames_index = match self.filename_to_index.get(&c_filename) {
126126
Some(index) => *index,
127127
None => {
128128
let index = self.filenames.len() as u32;
129-
self.filenames.push(filename.clone());
130-
self.filename_to_index.insert(filename.clone(), index);
129+
self.filenames.push(c_filename.clone());
130+
self.filename_to_index.insert(c_filename.clone(), index);
131131
index
132132
}
133133
};

‎src/librustc_codegen_llvm/coverageinfo/mod.rs

+13-27
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::common::CodegenCx;
66
use libc::c_uint;
77
use llvm::coverageinfo::CounterMappingRegion;
88
use log::debug;
9-
use rustc_codegen_ssa::coverageinfo::map::{CounterExpression, ExprKind, FunctionCoverage};
9+
use rustc_codegen_ssa::coverageinfo::map::{CounterExpression, ExprKind, FunctionCoverage, Region};
1010
use rustc_codegen_ssa::traits::{
1111
BaseTypeMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, StaticMethods,
1212
};
@@ -49,19 +49,18 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
4949
instance: Instance<'tcx>,
5050
function_source_hash: u64,
5151
id: u32,
52-
start_byte_pos: u32,
53-
end_byte_pos: u32,
52+
region: Region<'tcx>,
5453
) {
5554
debug!(
5655
"adding counter to coverage_regions: instance={:?}, function_source_hash={}, id={}, \
57-
byte range {}..{}",
58-
instance, function_source_hash, id, start_byte_pos, end_byte_pos,
56+
at {:?}",
57+
instance, function_source_hash, id, region,
5958
);
6059
let mut coverage_regions = self.coverage_context().function_coverage_map.borrow_mut();
6160
coverage_regions
6261
.entry(instance)
6362
.or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
64-
.add_counter(function_source_hash, id, start_byte_pos, end_byte_pos);
63+
.add_counter(function_source_hash, id, region);
6564
}
6665

6766
fn add_counter_expression_region(
@@ -71,43 +70,30 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
7170
lhs: u32,
7271
op: ExprKind,
7372
rhs: u32,
74-
start_byte_pos: u32,
75-
end_byte_pos: u32,
73+
region: Region<'tcx>,
7674
) {
7775
debug!(
7876
"adding counter expression to coverage_regions: instance={:?}, id={}, {} {:?} {}, \
79-
byte range {}..{}",
80-
instance, id_descending_from_max, lhs, op, rhs, start_byte_pos, end_byte_pos,
77+
at {:?}",
78+
instance, id_descending_from_max, lhs, op, rhs, region,
8179
);
8280
let mut coverage_regions = self.coverage_context().function_coverage_map.borrow_mut();
8381
coverage_regions
8482
.entry(instance)
8583
.or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
86-
.add_counter_expression(
87-
id_descending_from_max,
88-
lhs,
89-
op,
90-
rhs,
91-
start_byte_pos,
92-
end_byte_pos,
93-
);
84+
.add_counter_expression(id_descending_from_max, lhs, op, rhs, region);
9485
}
9586

96-
fn add_unreachable_region(
97-
&mut self,
98-
instance: Instance<'tcx>,
99-
start_byte_pos: u32,
100-
end_byte_pos: u32,
101-
) {
87+
fn add_unreachable_region(&mut self, instance: Instance<'tcx>, region: Region<'tcx>) {
10288
debug!(
103-
"adding unreachable code to coverage_regions: instance={:?}, byte range {}..{}",
104-
instance, start_byte_pos, end_byte_pos,
89+
"adding unreachable code to coverage_regions: instance={:?}, at {:?}",
90+
instance, region,
10591
);
10692
let mut coverage_regions = self.coverage_context().function_coverage_map.borrow_mut();
10793
coverage_regions
10894
.entry(instance)
10995
.or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
110-
.add_unreachable_region(start_byte_pos, end_byte_pos);
96+
.add_unreachable_region(region);
11197
}
11298
}
11399

‎src/librustc_codegen_llvm/intrinsic.rs

+61-60
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_ast::ast;
1313
use rustc_codegen_ssa::base::{compare_simd_types, to_immediate, wants_msvc_seh};
1414
use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
1515
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
16-
use rustc_codegen_ssa::coverageinfo::ExprKind;
16+
use rustc_codegen_ssa::coverageinfo;
1717
use rustc_codegen_ssa::glue;
1818
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
1919
use rustc_codegen_ssa::mir::place::PlaceRef;
@@ -93,64 +93,64 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
9393
let mut is_codegen_intrinsic = true;
9494
// Set `is_codegen_intrinsic` to `false` to bypass `codegen_intrinsic_call()`.
9595

96-
if self.tcx.sess.opts.debugging_opts.instrument_coverage {
97-
// If the intrinsic is from the local MIR, add the coverage information to the Codegen
98-
// context, to be encoded into the local crate's coverage map.
99-
if caller_instance.def_id().is_local() {
100-
// FIXME(richkadel): Make sure to add coverage analysis tests on a crate with
101-
// external crate dependencies, where:
102-
// 1. Both binary and dependent crates are compiled with `-Zinstrument-coverage`
103-
// 2. Only binary is compiled with `-Zinstrument-coverage`
104-
// 3. Only dependent crates are compiled with `-Zinstrument-coverage`
105-
match intrinsic {
106-
sym::count_code_region => {
107-
use coverage::count_code_region_args::*;
108-
self.add_counter_region(
109-
caller_instance,
110-
op_to_u64(&args[FUNCTION_SOURCE_HASH]),
111-
op_to_u32(&args[COUNTER_ID]),
112-
op_to_u32(&args[START_BYTE_POS]),
113-
op_to_u32(&args[END_BYTE_POS]),
114-
);
115-
}
116-
sym::coverage_counter_add | sym::coverage_counter_subtract => {
117-
use coverage::coverage_counter_expression_args::*;
118-
self.add_counter_expression_region(
119-
caller_instance,
120-
op_to_u32(&args[EXPRESSION_ID]),
121-
op_to_u32(&args[LEFT_ID]),
122-
if intrinsic == sym::coverage_counter_add {
123-
ExprKind::Add
124-
} else {
125-
ExprKind::Subtract
126-
},
127-
op_to_u32(&args[RIGHT_ID]),
128-
op_to_u32(&args[START_BYTE_POS]),
129-
op_to_u32(&args[END_BYTE_POS]),
130-
);
131-
}
132-
sym::coverage_unreachable => {
133-
use coverage::coverage_unreachable_args::*;
134-
self.add_unreachable_region(
135-
caller_instance,
136-
op_to_u32(&args[START_BYTE_POS]),
137-
op_to_u32(&args[END_BYTE_POS]),
138-
);
139-
}
140-
_ => {}
141-
}
96+
// FIXME(richkadel): Make sure to add coverage analysis tests on a crate with
97+
// external crate dependencies, where:
98+
// 1. Both binary and dependent crates are compiled with `-Zinstrument-coverage`
99+
// 2. Only binary is compiled with `-Zinstrument-coverage`
100+
// 3. Only dependent crates are compiled with `-Zinstrument-coverage`
101+
match intrinsic {
102+
sym::count_code_region => {
103+
use coverage::count_code_region_args::*;
104+
self.add_counter_region(
105+
caller_instance,
106+
op_to_u64(&args[FUNCTION_SOURCE_HASH]),
107+
op_to_u32(&args[COUNTER_ID]),
108+
coverageinfo::Region::new(
109+
op_to_str_slice(&args[FILE_NAME]),
110+
op_to_u32(&args[START_LINE]),
111+
op_to_u32(&args[START_COL]),
112+
op_to_u32(&args[END_LINE]),
113+
op_to_u32(&args[END_COL]),
114+
),
115+
);
142116
}
143-
144-
// Only the `count_code_region` coverage intrinsic is translated into an actual LLVM
145-
// intrinsic call (local or not); otherwise, set `is_codegen_intrinsic` to `false`.
146-
match intrinsic {
147-
sym::coverage_counter_add
148-
| sym::coverage_counter_subtract
149-
| sym::coverage_unreachable => {
150-
is_codegen_intrinsic = false;
151-
}
152-
_ => {}
117+
sym::coverage_counter_add | sym::coverage_counter_subtract => {
118+
is_codegen_intrinsic = false;
119+
use coverage::coverage_counter_expression_args::*;
120+
self.add_counter_expression_region(
121+
caller_instance,
122+
op_to_u32(&args[EXPRESSION_ID]),
123+
op_to_u32(&args[LEFT_ID]),
124+
if intrinsic == sym::coverage_counter_add {
125+
coverageinfo::ExprKind::Add
126+
} else {
127+
coverageinfo::ExprKind::Subtract
128+
},
129+
op_to_u32(&args[RIGHT_ID]),
130+
coverageinfo::Region::new(
131+
op_to_str_slice(&args[FILE_NAME]),
132+
op_to_u32(&args[START_LINE]),
133+
op_to_u32(&args[START_COL]),
134+
op_to_u32(&args[END_LINE]),
135+
op_to_u32(&args[END_COL]),
136+
),
137+
);
153138
}
139+
sym::coverage_unreachable => {
140+
is_codegen_intrinsic = false;
141+
use coverage::coverage_unreachable_args::*;
142+
self.add_unreachable_region(
143+
caller_instance,
144+
coverageinfo::Region::new(
145+
op_to_str_slice(&args[FILE_NAME]),
146+
op_to_u32(&args[START_LINE]),
147+
op_to_u32(&args[START_COL]),
148+
op_to_u32(&args[END_LINE]),
149+
op_to_u32(&args[END_COL]),
150+
),
151+
);
152+
}
153+
_ => {}
154154
}
155155
is_codegen_intrinsic
156156
}
@@ -215,9 +215,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
215215
self.call(llfn, &[], None)
216216
}
217217
sym::count_code_region => {
218-
// FIXME(richkadel): The current implementation assumes the MIR for the given
219-
// caller_instance represents a single function. Validate and/or correct if inlining
220-
// and/or monomorphization invalidates these assumptions.
221218
let coverageinfo = tcx.coverageinfo(caller_instance.def_id());
222219
let mangled_fn = tcx.symbol_name(caller_instance);
223220
let (mangled_fn_name, _len_val) = self.const_str(Symbol::intern(mangled_fn.name));
@@ -2283,6 +2280,10 @@ fn float_type_width(ty: Ty<'_>) -> Option<u64> {
22832280
}
22842281
}
22852282

2283+
fn op_to_str_slice<'tcx>(op: &Operand<'tcx>) -> &'tcx str {
2284+
Operand::value_from_const(op).try_to_str_slice().expect("Value is &str")
2285+
}
2286+
22862287
fn op_to_u32<'tcx>(op: &Operand<'tcx>) -> u32 {
22872288
Operand::scalar_from_const(op).to_u32().expect("Scalar is u32")
22882289
}

‎src/librustc_codegen_ssa/coverageinfo/map.rs

+37-147
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,8 @@ pub use super::ffi::*;
33
use rustc_index::vec::IndexVec;
44
use rustc_middle::ty::Instance;
55
use rustc_middle::ty::TyCtxt;
6-
use rustc_span::source_map::{Pos, SourceMap};
7-
use rustc_span::{BytePos, FileName, Loc, RealFileName};
86

9-
use std::cmp::{Ord, Ordering};
10-
use std::fmt;
11-
use std::path::PathBuf;
7+
use std::cmp::Ord;
128

139
rustc_index::newtype_index! {
1410
pub struct ExpressionOperandId {
@@ -38,127 +34,35 @@ rustc_index::newtype_index! {
3834
}
3935
}
4036

41-
#[derive(Clone, Debug)]
42-
pub struct Region {
43-
start: Loc,
44-
end: Loc,
45-
}
46-
47-
impl Ord for Region {
48-
fn cmp(&self, other: &Self) -> Ordering {
49-
(&self.start.file.name, &self.start.line, &self.start.col, &self.end.line, &self.end.col)
50-
.cmp(&(
51-
&other.start.file.name,
52-
&other.start.line,
53-
&other.start.col,
54-
&other.end.line,
55-
&other.end.col,
56-
))
57-
}
58-
}
59-
60-
impl PartialOrd for Region {
61-
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
62-
Some(self.cmp(other))
63-
}
64-
}
65-
66-
impl PartialEq for Region {
67-
fn eq(&self, other: &Self) -> bool {
68-
self.start.file.name == other.start.file.name
69-
&& self.start.line == other.start.line
70-
&& self.start.col == other.start.col
71-
&& self.end.line == other.end.line
72-
&& self.end.col == other.end.col
73-
}
74-
}
75-
76-
impl Eq for Region {}
77-
78-
impl fmt::Display for Region {
79-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80-
let (file_path, start_line, start_col, end_line, end_col) = self.file_start_and_end();
81-
write!(f, "{:?}:{}:{} - {}:{}", file_path, start_line, start_col, end_line, end_col)
82-
}
37+
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
38+
pub struct Region<'tcx> {
39+
pub file_name: &'tcx str,
40+
pub start_line: u32,
41+
pub start_col: u32,
42+
pub end_line: u32,
43+
pub end_col: u32,
8344
}
8445

85-
impl Region {
86-
pub fn new(source_map: &SourceMap, start_byte_pos: u32, end_byte_pos: u32) -> Self {
87-
let start = source_map.lookup_char_pos(BytePos::from_u32(start_byte_pos));
88-
let end = source_map.lookup_char_pos(BytePos::from_u32(end_byte_pos));
89-
assert_eq!(
90-
start.file.name, end.file.name,
91-
"Region start ({} -> {:?}) and end ({} -> {:?}) don't come from the same source file!",
92-
start_byte_pos, start, end_byte_pos, end
93-
);
94-
Self { start, end }
95-
}
96-
97-
pub fn file_start_and_end<'a>(&'a self) -> (&'a PathBuf, u32, u32, u32, u32) {
98-
let start = &self.start;
99-
let end = &self.end;
100-
match &start.file.name {
101-
FileName::Real(RealFileName::Named(path)) => (
102-
path,
103-
start.line as u32,
104-
start.col.to_u32() + 1,
105-
end.line as u32,
106-
end.col.to_u32() + 1,
107-
),
108-
_ => {
109-
bug!("start.file.name should be a RealFileName, but it was: {:?}", start.file.name)
110-
}
111-
}
46+
impl<'tcx> Region<'tcx> {
47+
pub fn new(
48+
file_name: &'tcx str,
49+
start_line: u32,
50+
start_col: u32,
51+
end_line: u32,
52+
end_col: u32,
53+
) -> Self {
54+
Self { file_name, start_line, start_col, end_line, end_col }
11255
}
11356
}
11457

11558
#[derive(Clone, Debug)]
116-
pub struct ExpressionRegion {
59+
pub struct ExpressionRegion<'tcx> {
11760
lhs: ExpressionOperandId,
11861
op: ExprKind,
11962
rhs: ExpressionOperandId,
120-
region: Region,
63+
region: Region<'tcx>,
12164
}
12265

123-
// FIXME(richkadel): There seems to be a problem computing the file location in
124-
// some cases. I need to investigate this more. When I generate and show coverage
125-
// for the example binary in the crates.io crate `json5format`, I had a couple of
126-
// notable problems:
127-
//
128-
// 1. I saw a lot of coverage spans in `llvm-cov show` highlighting regions in
129-
// various comments (not corresponding to rustdoc code), indicating a possible
130-
// problem with the byte_pos-to-source-map implementation.
131-
//
132-
// 2. And (perhaps not related) when I build the aforementioned example binary with:
133-
// `RUST_FLAGS="-Zinstrument-coverage" cargo build --example formatjson5`
134-
// and then run that binary with
135-
// `LLVM_PROFILE_FILE="formatjson5.profraw" ./target/debug/examples/formatjson5 \
136-
// some.json5` for some reason the binary generates *TWO* `.profraw` files. One
137-
// named `default.profraw` and the other named `formatjson5.profraw` (the expected
138-
// name, in this case).
139-
//
140-
// 3. I think that if I eliminate regions within a function, their region_ids,
141-
// referenced in expressions, will be wrong? I think the ids are implied by their
142-
// array position in the final coverage map output (IIRC).
143-
//
144-
// 4. I suspect a problem (if not the only problem) is the SourceMap is wrong for some
145-
// region start/end byte positions. Just like I couldn't get the function hash at
146-
// intrinsic codegen time for external crate functions, I think the SourceMap I
147-
// have here only applies to the local crate, and I know I have coverages that
148-
// reference external crates.
149-
//
150-
// I still don't know if I fixed the hash problem correctly. If external crates
151-
// implement the function, can't I use the coverage counters already compiled
152-
// into those external crates? (Maybe not for generics and/or maybe not for
153-
// macros... not sure. But I need to understand this better.)
154-
//
155-
// If the byte range conversion is wrong, fix it. But if it
156-
// is right, then it is possible for the start and end to be in different files.
157-
// Can I do something other than ignore coverages that span multiple files?
158-
//
159-
// If I can resolve this, remove the "Option<>" result type wrapper
160-
// `regions_in_file_order()` accordingly.
161-
16266
/// Collects all of the coverage regions associated with (a) injected counters, (b) counter
16367
/// expressions (additions or subtraction), and (c) unreachable regions (always counted as zero),
16468
/// for a given Function. Counters and counter expressions have non-overlapping `id`s because they
@@ -171,19 +75,17 @@ pub struct ExpressionRegion {
17175
/// only whitespace or comments). According to LLVM Code Coverage Mapping documentation, "A count
17276
/// for a gap area is only used as the line execution count if there are no other regions on a
17377
/// line."
174-
pub struct FunctionCoverage<'a> {
175-
source_map: &'a SourceMap,
78+
pub struct FunctionCoverage<'tcx> {
17679
source_hash: u64,
177-
counters: IndexVec<CounterValueReference, Option<Region>>,
178-
expressions: IndexVec<InjectedExpressionIndex, Option<ExpressionRegion>>,
179-
unreachable_regions: Vec<Region>,
80+
counters: IndexVec<CounterValueReference, Option<Region<'tcx>>>,
81+
expressions: IndexVec<InjectedExpressionIndex, Option<ExpressionRegion<'tcx>>>,
82+
unreachable_regions: Vec<Region<'tcx>>,
18083
}
18184

182-
impl<'a> FunctionCoverage<'a> {
183-
pub fn new<'tcx: 'a>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self {
85+
impl<'tcx> FunctionCoverage<'tcx> {
86+
pub fn new(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self {
18487
let coverageinfo = tcx.coverageinfo(instance.def_id());
18588
Self {
186-
source_map: tcx.sess.source_map(),
18789
source_hash: 0, // will be set with the first `add_counter()`
18890
counters: IndexVec::from_elem_n(None, coverageinfo.num_counters as usize),
18991
expressions: IndexVec::from_elem_n(None, coverageinfo.num_expressions as usize),
@@ -194,20 +96,14 @@ impl<'a> FunctionCoverage<'a> {
19496
/// Adds a code region to be counted by an injected counter intrinsic.
19597
/// The source_hash (computed during coverage instrumentation) should also be provided, and
19698
/// should be the same for all counters in a given function.
197-
pub fn add_counter(
198-
&mut self,
199-
source_hash: u64,
200-
id: u32,
201-
start_byte_pos: u32,
202-
end_byte_pos: u32,
203-
) {
99+
pub fn add_counter(&mut self, source_hash: u64, id: u32, region: Region<'tcx>) {
204100
if self.source_hash == 0 {
205101
self.source_hash = source_hash;
206102
} else {
207103
debug_assert_eq!(source_hash, self.source_hash);
208104
}
209105
self.counters[CounterValueReference::from(id)]
210-
.replace(Region::new(self.source_map, start_byte_pos, end_byte_pos))
106+
.replace(region)
211107
.expect_none("add_counter called with duplicate `id`");
212108
}
213109

@@ -231,27 +127,21 @@ impl<'a> FunctionCoverage<'a> {
231127
lhs: u32,
232128
op: ExprKind,
233129
rhs: u32,
234-
start_byte_pos: u32,
235-
end_byte_pos: u32,
130+
region: Region<'tcx>,
236131
) {
237132
let expression_id = ExpressionOperandId::from(id_descending_from_max);
238133
let lhs = ExpressionOperandId::from(lhs);
239134
let rhs = ExpressionOperandId::from(rhs);
240135

241136
let expression_index = self.expression_index(expression_id);
242137
self.expressions[expression_index]
243-
.replace(ExpressionRegion {
244-
lhs,
245-
op,
246-
rhs,
247-
region: Region::new(self.source_map, start_byte_pos, end_byte_pos),
248-
})
138+
.replace(ExpressionRegion { lhs, op, rhs, region })
249139
.expect_none("add_counter_expression called with duplicate `id_descending_from_max`");
250140
}
251141

252142
/// Add a region that will be marked as "unreachable", with a constant "zero counter".
253-
pub fn add_unreachable_region(&mut self, start_byte_pos: u32, end_byte_pos: u32) {
254-
self.unreachable_regions.push(Region::new(self.source_map, start_byte_pos, end_byte_pos));
143+
pub fn add_unreachable_region(&mut self, region: Region<'tcx>) {
144+
self.unreachable_regions.push(region)
255145
}
256146

257147
/// Return the source hash, generated from the HIR node structure, and used to indicate whether
@@ -264,8 +154,8 @@ impl<'a> FunctionCoverage<'a> {
264154
/// associated `Regions` (from which the LLVM-specific `CoverageMapGenerator` will create
265155
/// `CounterMappingRegion`s.
266156
pub fn get_expressions_and_counter_regions(
267-
&'a self,
268-
) -> (Vec<CounterExpression>, impl Iterator<Item = (Counter, &'a Region)>) {
157+
&'tcx self,
158+
) -> (Vec<CounterExpression>, impl Iterator<Item = (Counter, &'tcx Region<'tcx>)>) {
269159
assert!(self.source_hash != 0);
270160

271161
let counter_regions = self.counter_regions();
@@ -277,7 +167,7 @@ impl<'a> FunctionCoverage<'a> {
277167
(counter_expressions, counter_regions)
278168
}
279169

280-
fn counter_regions(&'a self) -> impl Iterator<Item = (Counter, &'a Region)> {
170+
fn counter_regions(&'tcx self) -> impl Iterator<Item = (Counter, &'tcx Region<'tcx>)> {
281171
self.counters.iter_enumerated().filter_map(|(index, entry)| {
282172
// Option::map() will return None to filter out missing counters. This may happen
283173
// if, for example, a MIR-instrumented counter is removed during an optimization.
@@ -288,8 +178,8 @@ impl<'a> FunctionCoverage<'a> {
288178
}
289179

290180
fn expressions_with_regions(
291-
&'a self,
292-
) -> (Vec<CounterExpression>, impl Iterator<Item = (Counter, &'a Region)>) {
181+
&'tcx self,
182+
) -> (Vec<CounterExpression>, impl Iterator<Item = (Counter, &'tcx Region<'tcx>)>) {
293183
let mut counter_expressions = Vec::with_capacity(self.expressions.len());
294184
let mut expression_regions = Vec::with_capacity(self.expressions.len());
295185
let mut new_indexes =
@@ -350,7 +240,7 @@ impl<'a> FunctionCoverage<'a> {
350240
(counter_expressions, expression_regions.into_iter())
351241
}
352242

353-
fn unreachable_regions(&'a self) -> impl Iterator<Item = (Counter, &'a Region)> {
243+
fn unreachable_regions(&'tcx self) -> impl Iterator<Item = (Counter, &'tcx Region<'tcx>)> {
354244
self.unreachable_regions.iter().map(|region| (Counter::zero(), region))
355245
}
356246

‎src/librustc_codegen_ssa/coverageinfo/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ pub mod ffi;
22
pub mod map;
33

44
pub use map::ExprKind;
5+
pub use map::Region;
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::BackendTypes;
2-
use crate::coverageinfo::ExprKind;
2+
use crate::coverageinfo::{ExprKind, Region};
33
use rustc_middle::ty::Instance;
44

55
pub trait CoverageInfoMethods: BackendTypes {
@@ -12,8 +12,7 @@ pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes {
1212
instance: Instance<'tcx>,
1313
function_source_hash: u64,
1414
index: u32,
15-
start_byte_pos: u32,
16-
end_byte_pos: u32,
15+
region: Region<'tcx>,
1716
);
1817

1918
fn add_counter_expression_region(
@@ -23,14 +22,8 @@ pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes {
2322
lhs: u32,
2423
op: ExprKind,
2524
rhs: u32,
26-
start_byte_pos: u32,
27-
end_byte_pos: u32,
25+
region: Region<'tcx>,
2826
);
2927

30-
fn add_unreachable_region(
31-
&mut self,
32-
instance: Instance<'tcx>,
33-
start_byte_pos: u32,
34-
end_byte_pos: u32,
35-
);
28+
fn add_unreachable_region(&mut self, instance: Instance<'tcx>, region: Region<'tcx>);
3629
}

‎src/librustc_middle/mir/coverage/mod.rs

+15-6
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
pub mod count_code_region_args {
55
pub const FUNCTION_SOURCE_HASH: usize = 0;
66
pub const COUNTER_ID: usize = 1;
7-
pub const START_BYTE_POS: usize = 2;
8-
pub const END_BYTE_POS: usize = 3;
7+
pub const FILE_NAME: usize = 2;
8+
pub const START_LINE: usize = 3;
9+
pub const START_COL: usize = 4;
10+
pub const END_LINE: usize = 5;
11+
pub const END_COL: usize = 6;
912
}
1013

1114
/// Positional arguments to `libcore::coverage_counter_add()` and
@@ -14,12 +17,18 @@ pub mod coverage_counter_expression_args {
1417
pub const EXPRESSION_ID: usize = 0;
1518
pub const LEFT_ID: usize = 1;
1619
pub const RIGHT_ID: usize = 2;
17-
pub const START_BYTE_POS: usize = 3;
18-
pub const END_BYTE_POS: usize = 4;
20+
pub const FILE_NAME: usize = 3;
21+
pub const START_LINE: usize = 4;
22+
pub const START_COL: usize = 5;
23+
pub const END_LINE: usize = 6;
24+
pub const END_COL: usize = 7;
1925
}
2026

2127
/// Positional arguments to `libcore::coverage_unreachable()`
2228
pub mod coverage_unreachable_args {
23-
pub const START_BYTE_POS: usize = 0;
24-
pub const END_BYTE_POS: usize = 1;
29+
pub const FILE_NAME: usize = 0;
30+
pub const START_LINE: usize = 1;
31+
pub const START_COL: usize = 2;
32+
pub const END_LINE: usize = 3;
33+
pub const END_COL: usize = 4;
2534
}

‎src/librustc_middle/mir/interpret/value.rs

+9
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,15 @@ impl<'tcx> ConstValue<'tcx> {
5656
}
5757
}
5858

59+
pub fn try_to_str_slice(&self) -> Option<&'tcx str> {
60+
if let ConstValue::Slice { data, start, end } = *self {
61+
::std::str::from_utf8(data.inspect_with_undef_and_ptr_outside_interpreter(start..end))
62+
.ok()
63+
} else {
64+
None
65+
}
66+
}
67+
5968
pub fn try_to_bits(&self, size: Size) -> Option<u128> {
6069
self.try_to_scalar()?.to_bits(size).ok()
6170
}

‎src/librustc_middle/mir/mod.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//!
33
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
44
5-
use crate::mir::interpret::{GlobalAlloc, Scalar};
5+
use crate::mir::interpret::{Allocation, ConstValue, GlobalAlloc, Scalar};
66
use crate::mir::visit::MirVisitable;
77
use crate::ty::adjustment::PointerCast;
88
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
@@ -1842,6 +1842,33 @@ impl<'tcx> Operand<'tcx> {
18421842
}
18431843
}
18441844

1845+
/// Convenience helper to make a literal-like constant from a given `&str` slice.
1846+
/// Since this is used to synthesize MIR, assumes `user_ty` is None.
1847+
pub fn const_from_str(tcx: TyCtxt<'tcx>, val: &str, span: Span) -> Operand<'tcx> {
1848+
let tcx = tcx;
1849+
let allocation = Allocation::from_byte_aligned_bytes(val.as_bytes());
1850+
let allocation = tcx.intern_const_alloc(allocation);
1851+
let const_val = ConstValue::Slice { data: allocation, start: 0, end: val.len() };
1852+
let ty = tcx.mk_imm_ref(tcx.lifetimes.re_erased, tcx.types.str_);
1853+
Operand::Constant(box Constant {
1854+
span,
1855+
user_ty: None,
1856+
literal: ty::Const::from_value(tcx, const_val, ty),
1857+
})
1858+
}
1859+
1860+
/// Convenience helper to make a `ConstValue` from the given `Operand`, assuming that `Operand`
1861+
/// wraps a constant value (such as a `&str` slice). Panics if this is not the case.
1862+
pub fn value_from_const(operand: &Operand<'tcx>) -> ConstValue<'tcx> {
1863+
match operand {
1864+
Operand::Constant(constant) => match constant.literal.val.try_to_value() {
1865+
Some(const_value) => const_value,
1866+
_ => panic!("{:?}: ConstValue expected", constant.literal.val),
1867+
},
1868+
_ => panic!("{:?}: Constant expected", operand),
1869+
}
1870+
}
1871+
18451872
pub fn to_copy(&self) -> Self {
18461873
match *self {
18471874
Operand::Copy(_) | Operand::Constant(_) => self.clone(),

‎src/librustc_mir/transform/instrument_coverage.rs

+61-33
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,19 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
55
use rustc_hir::lang_items;
66
use rustc_middle::hir;
77
use rustc_middle::ich::StableHashingContext;
8+
use rustc_middle::mir;
89
use rustc_middle::mir::coverage::*;
910
use rustc_middle::mir::interpret::Scalar;
11+
use rustc_middle::mir::traversal;
1012
use rustc_middle::mir::{
11-
self, traversal, BasicBlock, BasicBlockData, CoverageInfo, Operand, Place, SourceInfo,
12-
SourceScope, StatementKind, Terminator, TerminatorKind,
13+
BasicBlock, BasicBlockData, CoverageInfo, Operand, Place, SourceInfo, SourceScope,
14+
StatementKind, Terminator, TerminatorKind,
1315
};
1416
use rustc_middle::ty;
1517
use rustc_middle::ty::query::Providers;
16-
use rustc_middle::ty::FnDef;
17-
use rustc_middle::ty::TyCtxt;
18+
use rustc_middle::ty::{FnDef, TyCtxt};
1819
use rustc_span::def_id::DefId;
19-
use rustc_span::{Pos, Span};
20+
use rustc_span::{FileName, Pos, RealFileName, Span};
2021

2122
/// Inserts call to count_code_region() as a placeholder to be replaced during code generation with
2223
/// the intrinsic llvm.instrprof.increment.
@@ -112,6 +113,7 @@ enum Op {
112113
struct InjectedCall<'tcx> {
113114
func: Operand<'tcx>,
114115
args: Vec<Operand<'tcx>>,
116+
span: Span,
115117
inject_at: Span,
116118
}
117119

@@ -179,12 +181,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
179181
let _ignore = mir_body;
180182
let id = self.next_counter();
181183
let function_source_hash = self.function_source_hash();
182-
let code_region = body_span;
183184
let scope = rustc_middle::mir::OUTERMOST_SOURCE_SCOPE;
184185
let is_cleanup = false;
185186
let next_block = rustc_middle::mir::START_BLOCK;
186187
self.inject_call(
187-
self.make_counter(id, function_source_hash, code_region),
188+
self.make_counter(id, function_source_hash, body_span),
188189
scope,
189190
is_cleanup,
190191
next_block,
@@ -201,28 +202,22 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
201202
let op = if add { Op::Add } else { Op::Subtract };
202203
let rhs = 2;
203204

204-
let code_region = body_span;
205205
let scope = rustc_middle::mir::OUTERMOST_SOURCE_SCOPE;
206206
let is_cleanup = false;
207207
let next_block = rustc_middle::mir::START_BLOCK;
208208

209209
let id = self.next_expression();
210210
self.inject_call(
211-
self.make_expression(id, code_region, lhs, op, rhs),
211+
self.make_expression(id, body_span, lhs, op, rhs),
212212
scope,
213213
is_cleanup,
214214
next_block,
215215
);
216216
}
217217
}
218218

219-
fn make_counter(
220-
&self,
221-
id: u32,
222-
function_source_hash: u64,
223-
code_region: Span,
224-
) -> InjectedCall<'tcx> {
225-
let inject_at = code_region.shrink_to_lo();
219+
fn make_counter(&self, id: u32, function_source_hash: u64, span: Span) -> InjectedCall<'tcx> {
220+
let inject_at = span.shrink_to_lo();
226221

227222
let func = function_handle(
228223
self.tcx,
@@ -239,24 +234,18 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
239234
debug_assert_eq!(COUNTER_ID, args.len());
240235
args.push(self.const_u32(id, inject_at));
241236

242-
debug_assert_eq!(START_BYTE_POS, args.len());
243-
args.push(self.const_u32(code_region.lo().to_u32(), inject_at));
244-
245-
debug_assert_eq!(END_BYTE_POS, args.len());
246-
args.push(self.const_u32(code_region.hi().to_u32(), inject_at));
247-
248-
InjectedCall { func, args, inject_at }
237+
InjectedCall { func, args, span, inject_at }
249238
}
250239

251240
fn make_expression(
252241
&self,
253242
id: u32,
254-
code_region: Span,
243+
span: Span,
255244
lhs: u32,
256245
op: Op,
257246
rhs: u32,
258247
) -> InjectedCall<'tcx> {
259-
let inject_at = code_region.shrink_to_lo();
248+
let inject_at = span.shrink_to_lo();
260249

261250
let func = function_handle(
262251
self.tcx,
@@ -282,13 +271,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
282271
debug_assert_eq!(RIGHT_ID, args.len());
283272
args.push(self.const_u32(rhs, inject_at));
284273

285-
debug_assert_eq!(START_BYTE_POS, args.len());
286-
args.push(self.const_u32(code_region.lo().to_u32(), inject_at));
287-
288-
debug_assert_eq!(END_BYTE_POS, args.len());
289-
args.push(self.const_u32(code_region.hi().to_u32(), inject_at));
290-
291-
InjectedCall { func, args, inject_at }
274+
InjectedCall { func, args, span, inject_at }
292275
}
293276

294277
fn inject_call(
@@ -298,7 +281,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
298281
is_cleanup: bool,
299282
next_block: BasicBlock,
300283
) {
301-
let InjectedCall { func, args, inject_at } = call;
284+
let InjectedCall { func, mut args, span, inject_at } = call;
302285
debug!(
303286
" injecting {}call to {:?}({:?}) at: {:?}, scope: {:?}",
304287
if is_cleanup { "cleanup " } else { "" },
@@ -310,6 +293,14 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
310293

311294
let mut patch = MirPatch::new(self.mir_body);
312295

296+
let (file_name, start_line, start_col, end_line, end_col) = self.code_region(&span);
297+
298+
args.push(self.const_str(&file_name, inject_at));
299+
args.push(self.const_u32(start_line, inject_at));
300+
args.push(self.const_u32(start_col, inject_at));
301+
args.push(self.const_u32(end_line, inject_at));
302+
args.push(self.const_u32(end_col, inject_at));
303+
313304
let temp = patch.new_temp(self.tcx.mk_unit(), inject_at);
314305
let new_block = patch.new_block(placeholder_block(inject_at, scope, is_cleanup));
315306
patch.patch_terminator(
@@ -335,6 +326,43 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
335326
self.mir_body.basic_blocks_mut().swap(next_block, new_block);
336327
}
337328

329+
/// Convert the Span into its file name, start line and column, and end line and column
330+
fn code_region(&self, span: &Span) -> (String, u32, u32, u32, u32) {
331+
let source_map = self.tcx.sess.source_map();
332+
let start = source_map.lookup_char_pos(span.lo());
333+
let end = if span.hi() == span.lo() {
334+
start.clone()
335+
} else {
336+
let end = source_map.lookup_char_pos(span.hi());
337+
debug_assert_eq!(
338+
start.file.name,
339+
end.file.name,
340+
"Region start ({:?} -> {:?}) and end ({:?} -> {:?}) don't come from the same source file!",
341+
span.lo(),
342+
start,
343+
span.hi(),
344+
end
345+
);
346+
end
347+
};
348+
match &start.file.name {
349+
FileName::Real(RealFileName::Named(path)) => (
350+
path.to_string_lossy().to_string(),
351+
start.line as u32,
352+
start.col.to_u32() + 1,
353+
end.line as u32,
354+
end.col.to_u32() + 1,
355+
),
356+
_ => {
357+
bug!("start.file.name should be a RealFileName, but it was: {:?}", start.file.name)
358+
}
359+
}
360+
}
361+
362+
fn const_str(&self, value: &str, span: Span) -> Operand<'tcx> {
363+
Operand::const_from_str(self.tcx, value, span)
364+
}
365+
338366
fn const_u32(&self, value: u32, span: Span) -> Operand<'tcx> {
339367
Operand::const_from_scalar(self.tcx, self.tcx.types.u32, Scalar::from_u32(value), span)
340368
}

‎src/librustc_typeck/check/intrinsic.rs

+34-5
Original file line numberDiff line numberDiff line change
@@ -379,17 +379,46 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
379379

380380
sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
381381

382-
sym::count_code_region => {
383-
(0, vec![tcx.types.u64, tcx.types.u32, tcx.types.u32, tcx.types.u32], tcx.mk_unit())
384-
}
382+
sym::count_code_region => (
383+
0,
384+
vec![
385+
tcx.types.u64,
386+
tcx.types.u32,
387+
tcx.mk_static_str(),
388+
tcx.types.u32,
389+
tcx.types.u32,
390+
tcx.types.u32,
391+
tcx.types.u32,
392+
],
393+
tcx.mk_unit(),
394+
),
385395

386396
sym::coverage_counter_add | sym::coverage_counter_subtract => (
387397
0,
388-
vec![tcx.types.u32, tcx.types.u32, tcx.types.u32, tcx.types.u32, tcx.types.u32],
398+
vec![
399+
tcx.types.u32,
400+
tcx.types.u32,
401+
tcx.types.u32,
402+
tcx.mk_static_str(),
403+
tcx.types.u32,
404+
tcx.types.u32,
405+
tcx.types.u32,
406+
tcx.types.u32,
407+
],
389408
tcx.mk_unit(),
390409
),
391410

392-
sym::coverage_unreachable => (0, vec![tcx.types.u32, tcx.types.u32], tcx.mk_unit()),
411+
sym::coverage_unreachable => (
412+
0,
413+
vec![
414+
tcx.mk_static_str(),
415+
tcx.types.u32,
416+
tcx.types.u32,
417+
tcx.types.u32,
418+
tcx.types.u32,
419+
],
420+
tcx.mk_unit(),
421+
),
393422

394423
other => {
395424
struct_span_err!(

‎src/test/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff

+25-7
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77

88
bb0: {
99
+ StorageLive(_1); // scope 0 at $DIR/instrument_coverage.rs:18:18: 18:18
10-
+ _1 = const std::intrinsics::count_code_region(const 10208505205182607101_u64, const 0_u32, const 529_u32, const 541_u32) -> bb2; // scope 0 at $DIR/instrument_coverage.rs:18:18: 18:18
10+
+ _1 = const std::intrinsics::count_code_region(const 10208505205182607101_u64, const 0_u32, const "$DIR/instrument_coverage.rs", const 18_u32, const 18_u32, const 20_u32, const 2_u32) -> bb2; // scope 0 at $DIR/instrument_coverage.rs:18:18: 18:18
1111
+ // ty::Const
12-
+ // + ty: unsafe extern "rust-intrinsic" fn(u64, u32, u32, u32) {std::intrinsics::count_code_region}
12+
+ // + ty: unsafe extern "rust-intrinsic" fn(u64, u32, &'static str, u32, u32, u32, u32) {std::intrinsics::count_code_region}
1313
+ // + val: Value(Scalar(<ZST>))
1414
+ // mir::Constant
1515
+ // + span: $DIR/instrument_coverage.rs:18:18: 18:18
16-
+ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u64, u32, u32, u32) {std::intrinsics::count_code_region}, val: Value(Scalar(<ZST>)) }
16+
+ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u64, u32, &'static str, u32, u32, u32, u32) {std::intrinsics::count_code_region}, val: Value(Scalar(<ZST>)) }
1717
+ // ty::Const
1818
+ // + ty: u64
1919
+ // + val: Value(Scalar(0x8dabe565aaa2aefd))
@@ -27,17 +27,35 @@
2727
+ // + span: $DIR/instrument_coverage.rs:18:18: 18:18
2828
+ // + literal: Const { ty: u32, val: Value(Scalar(0x00000000)) }
2929
+ // ty::Const
30+
+ // + ty: &str
31+
+ // + val: Value(Slice { data: Allocation { bytes: [47, 117, 115, 114, 47, 108, 111, 99, 97, 108, 47, 103, 111, 111, 103, 108, 101, 47, 104, 111, 109, 101, 47, 114, 105, 99, 104, 107, 97, 100, 101, 108, 47, 114, 117, 115, 116, 47, 115, 114, 99, 47, 116, 101, 115, 116, 47, 109, 105, 114, 45, 111, 112, 116, 47, 105, 110, 115, 116, 114, 117, 109, 101, 110, 116, 95, 99, 111, 118, 101, 114, 97, 103, 101, 46, 114, 115], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [18446744073709551615, 8191], len: Size { raw: 77 } }, size: Size { raw: 77 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 77 })
32+
+ // mir::Constant
33+
+ // + span: $DIR/instrument_coverage.rs:18:18: 18:18
34+
+ // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [47, 117, 115, 114, 47, 108, 111, 99, 97, 108, 47, 103, 111, 111, 103, 108, 101, 47, 104, 111, 109, 101, 47, 114, 105, 99, 104, 107, 97, 100, 101, 108, 47, 114, 117, 115, 116, 47, 115, 114, 99, 47, 116, 101, 115, 116, 47, 109, 105, 114, 45, 111, 112, 116, 47, 105, 110, 115, 116, 114, 117, 109, 101, 110, 116, 95, 99, 111, 118, 101, 114, 97, 103, 101, 46, 114, 115], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [18446744073709551615, 8191], len: Size { raw: 77 } }, size: Size { raw: 77 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 77 }) }
35+
+ // ty::Const
36+
+ // + ty: u32
37+
+ // + val: Value(Scalar(0x00000012))
38+
+ // mir::Constant
39+
+ // + span: $DIR/instrument_coverage.rs:18:18: 18:18
40+
+ // + literal: Const { ty: u32, val: Value(Scalar(0x00000012)) }
41+
+ // ty::Const
42+
+ // + ty: u32
43+
+ // + val: Value(Scalar(0x00000012))
44+
+ // mir::Constant
45+
+ // + span: $DIR/instrument_coverage.rs:18:18: 18:18
46+
+ // + literal: Const { ty: u32, val: Value(Scalar(0x00000012)) }
47+
+ // ty::Const
3048
+ // + ty: u32
31-
+ // + val: Value(Scalar(0x00000211))
49+
+ // + val: Value(Scalar(0x00000014))
3250
+ // mir::Constant
3351
+ // + span: $DIR/instrument_coverage.rs:18:18: 18:18
34-
+ // + literal: Const { ty: u32, val: Value(Scalar(0x00000211)) }
52+
+ // + literal: Const { ty: u32, val: Value(Scalar(0x00000014)) }
3553
+ // ty::Const
3654
+ // + ty: u32
37-
+ // + val: Value(Scalar(0x0000021d))
55+
+ // + val: Value(Scalar(0x00000002))
3856
+ // mir::Constant
3957
+ // + span: $DIR/instrument_coverage.rs:18:18: 18:18
40-
+ // + literal: Const { ty: u32, val: Value(Scalar(0x0000021d)) }
58+
+ // + literal: Const { ty: u32, val: Value(Scalar(0x00000002)) }
4159
+ }
4260
+
4361
+ bb1 (cleanup): {

‎src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff

+25-7
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
bb0: {
1212
- falseUnwind -> [real: bb1, cleanup: bb2]; // scope 0 at $DIR/instrument_coverage.rs:10:5: 14:6
1313
+ StorageLive(_4); // scope 0 at $DIR/instrument_coverage.rs:9:11: 9:11
14-
+ _4 = const std::intrinsics::count_code_region(const 16004455475339839479_u64, const 0_u32, const 425_u32, const 493_u32) -> bb7; // scope 0 at $DIR/instrument_coverage.rs:9:11: 9:11
14+
+ _4 = const std::intrinsics::count_code_region(const 16004455475339839479_u64, const 0_u32, const "$DIR/instrument_coverage.rs", const 9_u32, const 11_u32, const 15_u32, const 2_u32) -> bb7; // scope 0 at $DIR/instrument_coverage.rs:9:11: 9:11
1515
+ // ty::Const
16-
+ // + ty: unsafe extern "rust-intrinsic" fn(u64, u32, u32, u32) {std::intrinsics::count_code_region}
16+
+ // + ty: unsafe extern "rust-intrinsic" fn(u64, u32, &'static str, u32, u32, u32, u32) {std::intrinsics::count_code_region}
1717
+ // + val: Value(Scalar(<ZST>))
1818
+ // mir::Constant
1919
+ // + span: $DIR/instrument_coverage.rs:9:11: 9:11
20-
+ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u64, u32, u32, u32) {std::intrinsics::count_code_region}, val: Value(Scalar(<ZST>)) }
20+
+ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u64, u32, &'static str, u32, u32, u32, u32) {std::intrinsics::count_code_region}, val: Value(Scalar(<ZST>)) }
2121
+ // ty::Const
2222
+ // + ty: u64
2323
+ // + val: Value(Scalar(0xde1b3f75a72fc7f7))
@@ -31,17 +31,35 @@
3131
+ // + span: $DIR/instrument_coverage.rs:9:11: 9:11
3232
+ // + literal: Const { ty: u32, val: Value(Scalar(0x00000000)) }
3333
+ // ty::Const
34+
+ // + ty: &str
35+
+ // + val: Value(Slice { data: Allocation { bytes: [47, 117, 115, 114, 47, 108, 111, 99, 97, 108, 47, 103, 111, 111, 103, 108, 101, 47, 104, 111, 109, 101, 47, 114, 105, 99, 104, 107, 97, 100, 101, 108, 47, 114, 117, 115, 116, 47, 115, 114, 99, 47, 116, 101, 115, 116, 47, 109, 105, 114, 45, 111, 112, 116, 47, 105, 110, 115, 116, 114, 117, 109, 101, 110, 116, 95, 99, 111, 118, 101, 114, 97, 103, 101, 46, 114, 115], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [18446744073709551615, 8191], len: Size { raw: 77 } }, size: Size { raw: 77 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 77 })
36+
+ // mir::Constant
37+
+ // + span: $DIR/instrument_coverage.rs:9:11: 9:11
38+
+ // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [47, 117, 115, 114, 47, 108, 111, 99, 97, 108, 47, 103, 111, 111, 103, 108, 101, 47, 104, 111, 109, 101, 47, 114, 105, 99, 104, 107, 97, 100, 101, 108, 47, 114, 117, 115, 116, 47, 115, 114, 99, 47, 116, 101, 115, 116, 47, 109, 105, 114, 45, 111, 112, 116, 47, 105, 110, 115, 116, 114, 117, 109, 101, 110, 116, 95, 99, 111, 118, 101, 114, 97, 103, 101, 46, 114, 115], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [18446744073709551615, 8191], len: Size { raw: 77 } }, size: Size { raw: 77 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 77 }) }
39+
+ // ty::Const
40+
+ // + ty: u32
41+
+ // + val: Value(Scalar(0x00000009))
42+
+ // mir::Constant
43+
+ // + span: $DIR/instrument_coverage.rs:9:11: 9:11
44+
+ // + literal: Const { ty: u32, val: Value(Scalar(0x00000009)) }
45+
+ // ty::Const
46+
+ // + ty: u32
47+
+ // + val: Value(Scalar(0x0000000b))
48+
+ // mir::Constant
49+
+ // + span: $DIR/instrument_coverage.rs:9:11: 9:11
50+
+ // + literal: Const { ty: u32, val: Value(Scalar(0x0000000b)) }
51+
+ // ty::Const
3452
+ // + ty: u32
35-
+ // + val: Value(Scalar(0x000001a9))
53+
+ // + val: Value(Scalar(0x0000000f))
3654
+ // mir::Constant
3755
+ // + span: $DIR/instrument_coverage.rs:9:11: 9:11
38-
+ // + literal: Const { ty: u32, val: Value(Scalar(0x000001a9)) }
56+
+ // + literal: Const { ty: u32, val: Value(Scalar(0x0000000f)) }
3957
+ // ty::Const
4058
+ // + ty: u32
41-
+ // + val: Value(Scalar(0x000001ed))
59+
+ // + val: Value(Scalar(0x00000002))
4260
+ // mir::Constant
4361
+ // + span: $DIR/instrument_coverage.rs:9:11: 9:11
44-
+ // + literal: Const { ty: u32, val: Value(Scalar(0x000001ed)) }
62+
+ // + literal: Const { ty: u32, val: Value(Scalar(0x00000002)) }
4563
}
4664

4765
bb1: {

0 commit comments

Comments
 (0)
Please sign in to comment.