Skip to content

Commit a433777

Browse files
committed
Added codegen_llvm/coverageinfo mod for upcoming coverage map
1 parent d38359d commit a433777

File tree

12 files changed

+144
-72
lines changed

12 files changed

+144
-72
lines changed

src/librustc_codegen_llvm/base.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ pub fn compile_codegen_unit(
150150
cx.create_used_variable()
151151
}
152152

153+
// Finalize code coverage by injecting the coverage map
154+
if cx.sess().opts.debugging_opts.instrument_coverage {
155+
cx.coverageinfo_finalize();
156+
}
157+
153158
// Finalize debuginfo
154159
if cx.sess().opts.debuginfo != DebugInfo::None {
155160
cx.debuginfo_finalize();
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use crate::common::CodegenCx;
2+
use log::debug;
3+
use rustc_codegen_ssa::traits::CoverageInfoMethods;
4+
use rustc_hir::def_id::LOCAL_CRATE;
5+
6+
// FIXME(richkadel): This might not be where I put the coverage map generation, but it's a
7+
// placeholder for now.
8+
//
9+
// I need to inject the coverage map into the LLVM IR. This is one possible place to do it.
10+
//
11+
// The code below is here, at least temporarily, to verify that the `CoverageRegion`s are
12+
// available, to produce the coverage map.
13+
14+
/// Generates and exports the Coverage Map.
15+
pub fn finalize(cx: &CodegenCx<'_, '_>) {
16+
let instances = &*cx.instances.borrow();
17+
for instance in instances.keys() {
18+
if instance.def_id().krate == LOCAL_CRATE {
19+
// FIXME(richkadel): Is this check `krate == LOCAL_CRATE` right?
20+
//
21+
// NOTE: I'm considering at least one alternative to this loop on `instances`,
22+
// But if I do go with this, make sure the check on LOCAL_CRATE works for all cases.
23+
//
24+
//
25+
// Without it, I was crashing on some of the instances, with:
26+
//
27+
// src/librustc_metadata/rmeta/decoder.rs:1127:17: get_optimized_mir: missing MIR for `DefId(1:2867 ~ std[70cc]::io[0]::stdio[0]::_print[0])`
28+
//
29+
// This check avoids it, but still works for the very limited testing I've done so far.
30+
let coverageinfo = cx.tcx.coverageinfo(instance.def_id());
31+
if coverageinfo.num_counters > 0 {
32+
debug!(
33+
"Generate coverage map for: {}, hash: {:?}, num_counters: {}\n{}",
34+
instance,
35+
coverageinfo.hash,
36+
coverageinfo.num_counters,
37+
{
38+
let regions = &coverageinfo.coverage_regions;
39+
(0..regions.len() as u32)
40+
.map(|counter_index| {
41+
let region = &regions[counter_index];
42+
format!(
43+
" counter_index {} byte range: {}..{}",
44+
counter_index, region.start_byte_pos, region.end_byte_pos
45+
)
46+
})
47+
.collect::<Vec<String>>()
48+
.join("\n")
49+
}
50+
);
51+
}
52+
}
53+
}
54+
}
55+
56+
impl CoverageInfoMethods for CodegenCx<'ll, 'tcx> {
57+
fn coverageinfo_finalize(&self) {
58+
finalize(self)
59+
}
60+
}

src/librustc_codegen_llvm/intrinsic.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
1919
use rustc_codegen_ssa::traits::*;
2020
use rustc_codegen_ssa::MemFlags;
2121
use rustc_hir as hir;
22+
use rustc_middle::mir::coverage;
2223
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
2324
use rustc_middle::ty::{self, Ty};
2425
use rustc_middle::{bug, span_bug};
@@ -140,27 +141,24 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
140141
self.call(llfn, &[], None)
141142
}
142143
"count_code_region" => {
143-
use rustc_middle::mir::count_code_region_args::{
144-
COUNTER_INDEX, END_BYTE_POS, START_BYTE_POS,
145-
};
144+
use coverage::count_code_region_args::*;
146145
// FIXME(richkadel): The current implementation assumes the MIR for the given
147146
// caller_instance represents a single function. Validate and/or correct if inlining
148147
// and/or monomorphization invalidates these assumptions.
149-
let coverage_data = tcx.coverage_data(caller_instance.def_id());
148+
let coverageinfo = tcx.coverageinfo(caller_instance.def_id());
150149
let mangled_fn = tcx.symbol_name(caller_instance);
151150
let (mangled_fn_name, _len_val) = self.const_str(mangled_fn.name);
152-
let hash = self.const_u64(coverage_data.hash);
153-
let num_counters = self.const_u32(coverage_data.num_counters);
151+
let hash = self.const_u64(coverageinfo.hash);
152+
let num_counters = self.const_u32(coverageinfo.num_counters);
154153
let index = args[COUNTER_INDEX].immediate();
155154
debug!(
156-
"count_code_region to LLVM intrinsic instrprof.increment(fn_name={}, hash={:?}, num_counters={:?}, index={:?}), byte range {:?}..{:?}, coverage_regions: {:?}",
155+
"count_code_region to LLVM intrinsic instrprof.increment(fn_name={}, hash={:?}, num_counters={:?}, index={:?}), byte range {:?}..{:?}",
157156
mangled_fn.name,
158157
hash,
159158
num_counters,
160159
index,
161160
args[START_BYTE_POS].immediate(),
162161
args[END_BYTE_POS].immediate(),
163-
coverage_data.coverage_regions,
164162
);
165163
self.instrprof_increment(mangled_fn_name, hash, num_counters, index)
166164
}

src/librustc_codegen_llvm/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ mod callee;
5555
mod common;
5656
mod consts;
5757
mod context;
58+
mod coverageinfo;
5859
mod debuginfo;
5960
mod declare;
6061
mod intrinsic;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
use super::BackendTypes;
2+
3+
pub trait CoverageInfoMethods: BackendTypes {
4+
fn coverageinfo_finalize(&self);
5+
}

src/librustc_codegen_ssa/traits/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ mod asm;
1919
mod backend;
2020
mod builder;
2121
mod consts;
22+
mod coverageinfo;
2223
mod debuginfo;
2324
mod declare;
2425
mod intrinsic;
@@ -32,6 +33,7 @@ pub use self::asm::{AsmBuilderMethods, AsmMethods, InlineAsmOperandRef};
3233
pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods};
3334
pub use self::builder::{BuilderMethods, OverflowOp};
3435
pub use self::consts::ConstMethods;
36+
pub use self::coverageinfo::CoverageInfoMethods;
3537
pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods};
3638
pub use self::declare::{DeclareMethods, PreDefineMethods};
3739
pub use self::intrinsic::IntrinsicCallMethods;
@@ -56,6 +58,7 @@ pub trait CodegenMethods<'tcx>:
5658
+ MiscMethods<'tcx>
5759
+ ConstMethods<'tcx>
5860
+ StaticMethods
61+
+ CoverageInfoMethods
5962
+ DebugInfoMethods<'tcx>
6063
+ DeclareMethods<'tcx>
6164
+ AsmMethods
@@ -72,6 +75,7 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where
7275
+ MiscMethods<'tcx>
7376
+ ConstMethods<'tcx>
7477
+ StaticMethods
78+
+ CoverageInfoMethods
7579
+ DebugInfoMethods<'tcx>
7680
+ DeclareMethods<'tcx>
7781
+ AsmMethods

src/librustc_middle/arena.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ macro_rules! arena_types {
9494
[] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>, rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>;
9595
[] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation, rustc_middle::traits::ObjectSafetyViolation;
9696
[] codegen_unit: rustc_middle::mir::mono::CodegenUnit<$tcx>, rustc_middle::mir::mono::CodegenUnit<'_x>;
97-
[] coverage_data: rustc_middle::mir::CoverageData, rustc_middle::mir::CoverageData;
97+
[] coverageinfo: rustc_middle::mir::coverage::CoverageInfo, rustc_middle::mir::coverage::CoverageInfo;
9898
[] attribute: rustc_ast::ast::Attribute, rustc_ast::ast::Attribute;
9999
[] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>, rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>;
100100
[] hir_id_set: rustc_hir::HirIdSet, rustc_hir::HirIdSet;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//! Metadata from source code coverage analysis and instrumentation.
2+
3+
use rustc_index::vec::IndexVec;
4+
5+
/// Coverage information associated with each function (MIR) instrumented with coverage counters, when
6+
/// compiled with `-Zinstrument_coverage`. The query `tcx.coverageinfo(DefId)` computes these
7+
/// values on demand (during code generation). This query is only valid after executing the MIR pass
8+
/// `InstrumentCoverage`.
9+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
10+
pub struct CoverageInfo {
11+
/// A hash value that can be used by the consumer of the coverage profile data to detect
12+
/// changes to the instrumented source of the associated MIR body (typically, for an
13+
/// individual function).
14+
pub hash: u64,
15+
16+
/// The total number of coverage region counters added to the MIR `Body`.
17+
pub num_counters: u32,
18+
19+
/// The start and end positions within a source file for the region of source code counted by
20+
/// the given counter index.
21+
pub coverage_regions: IndexVec<u32, CoverageRegion>,
22+
}
23+
24+
/// Defines the region, within the source code, where a counter is optionally injected (if compiled
25+
/// with `-Zinstrument_coverage`), to count the number of times this code region is executed.
26+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
27+
pub struct CoverageRegion {
28+
/// The code region's starting position within the source code file.
29+
pub start_byte_pos: u32,
30+
31+
/// The code region's ending position within the source code file.
32+
pub end_byte_pos: u32,
33+
}
34+
35+
/// Positional arguments to `libcore::count_code_region()`
36+
pub mod count_code_region_args {
37+
pub const COUNTER_INDEX: usize = 0;
38+
pub const START_BYTE_POS: usize = 1;
39+
pub const END_BYTE_POS: usize = 2;
40+
}

src/librustc_middle/mir/mod.rs

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ use std::{iter, mem, option};
4242
use self::predecessors::{PredecessorCache, Predecessors};
4343
pub use self::query::*;
4444

45+
pub mod coverage;
4546
pub mod interpret;
4647
pub mod mono;
4748
mod predecessors;
@@ -2993,44 +2994,3 @@ impl Location {
29932994
}
29942995
}
29952996
}
2996-
2997-
///////////////////////////////////////////////////////////////////////////
2998-
// Source code coverage
2999-
3000-
/// Coverage data associated with each function (MIR) instrumented with coverage counters, when
3001-
/// compiled with `-Zinstrument_coverage`. The query `tcx.coverage_data(DefId)` computes these
3002-
/// values on demand (during code generation). This query is only valid after executing the MIR pass
3003-
/// `InstrumentCoverage`.
3004-
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
3005-
pub struct CoverageRegion {
3006-
/// The code region's starting position within the source code file.
3007-
pub start_byte_pos: u32,
3008-
3009-
/// The code region's ending position within the source code file.
3010-
pub end_byte_pos: u32,
3011-
}
3012-
3013-
/// Coverage data associated with each function (MIR) instrumented with coverage counters, when
3014-
/// compiled with `-Zinstrument_coverage`. The query `tcx.coverage_data(DefId)` computes these
3015-
/// values on demand (during code generation). This query is only valid after executing the MIR pass
3016-
/// `InstrumentCoverage`.
3017-
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
3018-
pub struct CoverageData {
3019-
/// A hash value that can be used by the consumer of the coverage profile data to detect
3020-
/// changes to the instrumented source of the associated MIR body (typically, for an
3021-
/// individual function).
3022-
pub hash: u64,
3023-
3024-
/// The total number of coverage region counters added to the MIR `Body`.
3025-
pub num_counters: u32,
3026-
3027-
/// The start and end positions within a source file for the region of source code counted by
3028-
/// the given counter index.
3029-
pub coverage_regions: IndexVec<u32, CoverageRegion>,
3030-
}
3031-
3032-
pub mod count_code_region_args {
3033-
pub const COUNTER_INDEX: usize = 0;
3034-
pub const START_BYTE_POS: usize = 1;
3035-
pub const END_BYTE_POS: usize = 2;
3036-
}

src/librustc_middle/query/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,8 @@ rustc_queries! {
231231
cache_on_disk_if { key.is_local() }
232232
}
233233

234-
query coverage_data(key: DefId) -> &'tcx mir::CoverageData {
235-
desc { |tcx| "retrieving coverage data from MIR for `{}`", tcx.def_path_str(key) }
234+
query coverageinfo(key: DefId) -> &'tcx mir::coverage::CoverageInfo {
235+
desc { |tcx| "retrieving coverageinfo from MIR for `{}`", tcx.def_path_str(key) }
236236
storage(ArenaCacheSelector<'tcx>)
237237
cache_on_disk_if { key.is_local() }
238238
}

0 commit comments

Comments
 (0)