Skip to content

Commit 566ad8d

Browse files
Swatinemrichkadel
authored andcommitted
Update CoverageMappingFormat Support to Version6
Version 5 adds Branch Regions which are a prerequisite for branch coverage. Version 6 can use the zeroth filename as prefix for other relative files.
1 parent 7b3cd07 commit 566ad8d

File tree

6 files changed

+66
-23
lines changed

6 files changed

+66
-23
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ use tracing::debug;
1717

1818
/// Generates and exports the Coverage Map.
1919
///
20-
/// This Coverage Map complies with Coverage Mapping Format version 4 (zero-based encoded as 3),
21-
/// as defined at [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format)
22-
/// and published in Rust's November 2020 fork of LLVM. This version is supported by the LLVM
23-
/// coverage tools (`llvm-profdata` and `llvm-cov`) bundled with Rust's fork of LLVM.
20+
/// This Coverage Map complies with Coverage Mapping Format version 5 (zero-based encoded as 4),
21+
/// as defined at [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
22+
/// This version is supported by the LLVM coverage tools (`llvm-profdata` and `llvm-cov`)
23+
/// bundled with Rust's fork of LLVM.
2424
///
2525
/// Consequently, Rust's bundled version of Clang also generates Coverage Maps compliant with
2626
/// the same version. Clang's implementation of Coverage Map generation was referenced when
@@ -30,12 +30,12 @@ use tracing::debug;
3030
pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
3131
let tcx = cx.tcx;
3232

33-
// Ensure LLVM supports Coverage Map Version 4 (encoded as a zero-based value: 3).
34-
// If not, the LLVM Version must be less than 11.
35-
let version = coverageinfo::mapping_version();
36-
if version != 3 {
37-
tcx.sess.fatal("rustc option `-Z instrument-coverage` requires LLVM 11 or higher.");
38-
}
33+
// While our bundled LLVM might support Coverage Map Version 6
34+
// (encoded as a zero-based value: 5), we clamp that to Version 5,
35+
// as Version 6 would require us to use the 0-th filename as a path prefix
36+
// for all other relative paths, which we don't take advantage of right now.
37+
let _version = coverageinfo::mapping_version();
38+
let version = 4;
3939

4040
debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name());
4141

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+40-2
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ pub type InlineAsmDiagHandler = unsafe extern "C" fn(&SMDiagnostic, *const c_voi
681681
pub mod coverageinfo {
682682
use super::coverage_map;
683683

684-
/// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L206-L222)
684+
/// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L209-L230)
685685
#[derive(Copy, Clone, Debug)]
686686
#[repr(C)]
687687
pub enum RegionKind {
@@ -700,11 +700,16 @@ pub mod coverageinfo {
700700
/// A GapRegion is like a CodeRegion, but its count is only set as the
701701
/// line execution count when its the only region in the line.
702702
GapRegion = 3,
703+
704+
/// A BranchRegion represents leaf-level boolean expressions and is
705+
/// associated with two counters, each representing the number of times the
706+
/// expression evaluates to true or false.
707+
BranchRegion = 4,
703708
}
704709

705710
/// This struct provides LLVM's representation of a "CoverageMappingRegion", encoded into the
706711
/// coverage map, in accordance with the
707-
/// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
712+
/// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
708713
/// The struct composes fields representing the `Counter` type and value(s) (injected counter
709714
/// ID, or expression type and operands), the source file (an indirect index into a "filenames
710715
/// array", encoded separately), and source location (start and end positions of the represented
@@ -717,6 +722,10 @@ pub mod coverageinfo {
717722
/// The counter type and type-dependent counter data, if any.
718723
counter: coverage_map::Counter,
719724

725+
/// If the `RegionKind` is a `BranchRegion`, this represents the counter
726+
/// for the false branch of the region.
727+
false_counter: coverage_map::Counter,
728+
720729
/// An indirect reference to the source filename. In the LLVM Coverage Mapping Format, the
721730
/// file_id is an index into a function-specific `virtual_file_mapping` array of indexes
722731
/// that, in turn, are used to look up the filename for this region.
@@ -754,6 +763,7 @@ pub mod coverageinfo {
754763
) -> Self {
755764
Self {
756765
counter,
766+
false_counter: coverage_map::Counter::zero(),
757767
file_id,
758768
expanded_file_id: 0,
759769
start_line,
@@ -764,6 +774,31 @@ pub mod coverageinfo {
764774
}
765775
}
766776

777+
// This function might be used in the future; the LLVM API is still evolving, as is coverage
778+
// support.
779+
#[allow(dead_code)]
780+
crate fn branch_region(
781+
counter: coverage_map::Counter,
782+
false_counter: coverage_map::Counter,
783+
file_id: u32,
784+
start_line: u32,
785+
start_col: u32,
786+
end_line: u32,
787+
end_col: u32,
788+
) -> Self {
789+
Self {
790+
counter,
791+
false_counter,
792+
file_id,
793+
expanded_file_id: 0,
794+
start_line,
795+
start_col,
796+
end_line,
797+
end_col,
798+
kind: RegionKind::BranchRegion,
799+
}
800+
}
801+
767802
// This function might be used in the future; the LLVM API is still evolving, as is coverage
768803
// support.
769804
#[allow(dead_code)]
@@ -777,6 +812,7 @@ pub mod coverageinfo {
777812
) -> Self {
778813
Self {
779814
counter: coverage_map::Counter::zero(),
815+
false_counter: coverage_map::Counter::zero(),
780816
file_id,
781817
expanded_file_id,
782818
start_line,
@@ -799,6 +835,7 @@ pub mod coverageinfo {
799835
) -> Self {
800836
Self {
801837
counter: coverage_map::Counter::zero(),
838+
false_counter: coverage_map::Counter::zero(),
802839
file_id,
803840
expanded_file_id: 0,
804841
start_line,
@@ -822,6 +859,7 @@ pub mod coverageinfo {
822859
) -> Self {
823860
Self {
824861
counter,
862+
false_counter: coverage_map::Counter::zero(),
825863
file_id,
826864
expanded_file_id: 0,
827865
start_line,

compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rustc_middle::mir::coverage::{CounterValueReference, MappedExpressionIndex};
22

3-
/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L206-L222)
3+
/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L95)
44
#[derive(Copy, Clone, Debug)]
55
#[repr(C)]
66
pub enum CounterKind {
@@ -17,7 +17,7 @@ pub enum CounterKind {
1717
/// `instrprof.increment()`)
1818
/// * For `CounterKind::Expression`, `id` is the index into the coverage map's array of
1919
/// counter expressions.
20-
/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L99-L100)
20+
/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L102-L103)
2121
/// Important: The Rust struct layout (order and types of fields) must match its C++ counterpart.
2222
#[derive(Copy, Clone, Debug)]
2323
#[repr(C)]
@@ -59,15 +59,15 @@ impl Counter {
5959
}
6060
}
6161

62-
/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L147)
62+
/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L150)
6363
#[derive(Copy, Clone, Debug)]
6464
#[repr(C)]
6565
pub enum ExprKind {
6666
Subtract = 0,
6767
Add = 1,
6868
}
6969

70-
/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L148-L149)
70+
/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L151-L152)
7171
/// Important: The Rust struct layout (order and types of fields) must match its C++
7272
/// counterpart.
7373
#[derive(Copy, Clone, Debug)]

compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ using namespace llvm;
1010

1111
struct LLVMRustCounterMappingRegion {
1212
coverage::Counter Count;
13+
coverage::Counter FalseCount;
1314
uint32_t FileID;
1415
uint32_t ExpandedFileID;
1516
uint32_t LineStart;
@@ -53,7 +54,7 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer(
5354
MappingRegions.reserve(NumMappingRegions);
5455
for (const auto &Region : makeArrayRef(RustMappingRegions, NumMappingRegions)) {
5556
MappingRegions.emplace_back(
56-
Region.Count, Region.FileID, Region.ExpandedFileID,
57+
Region.Count, Region.FalseCount, Region.FileID, Region.ExpandedFileID,
5758
Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd,
5859
Region.Kind);
5960
}
@@ -108,5 +109,9 @@ extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) {
108109
}
109110

110111
extern "C" uint32_t LLVMRustCoverageMappingVersion() {
111-
return coverage::CovMapVersion::Version4;
112+
#if LLVM_VERSION_GE(13, 0)
113+
return coverage::CovMapVersion::Version6;
114+
#else
115+
return coverage::CovMapVersion::Version5;
116+
#endif
112117
}

compiler/rustc_middle/src/mir/coverage.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ rustc_index::newtype_index! {
2121
impl ExpressionOperandId {
2222
/// An expression operand for a "zero counter", as described in the following references:
2323
///
24-
/// * <https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#counter>
25-
/// * <https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#tag>
26-
/// * <https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#counter-expressions>
24+
/// * <https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#counter>
25+
/// * <https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#tag>
26+
/// * <https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#counter-expressions>
2727
///
2828
/// This operand can be used to count two or more separate code regions with a single counter,
2929
/// if they run sequentially with no branches, by injecting the `Counter` in a `BasicBlock` for

src/doc/unstable-book/src/compiler-flags/instrument-coverage.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ This document describes how to enable and use the LLVM instrumentation-based cov
2020
When `-Z instrument-coverage` is enabled, the Rust compiler enhances rust-based libraries and binaries by:
2121

2222
- Automatically injecting calls to an LLVM intrinsic ([`llvm.instrprof.increment`]), at functions and branches in compiled code, to increment counters when conditional sections of code are executed.
23-
- Embedding additional information in the data section of each library and binary (using the [LLVM Code Coverage Mapping Format] _Version 4_, supported _only_ in LLVM 11 and up), to define the code regions (start and end positions in the source code) being counted.
23+
- Embedding additional information in the data section of each library and binary (using the [LLVM Code Coverage Mapping Format] _Version 5_, supported _only_ in LLVM 12 and up), to define the code regions (start and end positions in the source code) being counted.
2424

2525
When running a coverage-instrumented program, the counter values are written to a `profraw` file at program termination. LLVM bundles tools that read the counter results, combine those results with the coverage map (embedded in the program binary), and generate coverage reports in multiple formats.
2626

@@ -123,7 +123,7 @@ If `LLVM_PROFILE_FILE` contains a path to a non-existent directory, the missing
123123

124124
## Installing LLVM coverage tools
125125

126-
LLVM's supplies two tools—`llvm-profdata` and `llvm-cov`—that process coverage data and generate reports. There are several ways to find and/or install these tools, but note that the coverage mapping data generated by the Rust compiler requires LLVM version 11 or higher. (`llvm-cov --version` typically shows the tool's LLVM version number.):
126+
LLVM's supplies two tools—`llvm-profdata` and `llvm-cov`—that process coverage data and generate reports. There are several ways to find and/or install these tools, but note that the coverage mapping data generated by the Rust compiler requires LLVM version 12 or higher. (`llvm-cov --version` typically shows the tool's LLVM version number.):
127127

128128
- The LLVM tools may be installed (or installable) directly to your OS (such as via `apt-get`, for Linux).
129129
- If you are building the Rust compiler from source, you can optionally use the bundled LLVM tools, built from source. Those tool binaries can typically be found in your build platform directory at something like: `rust/build/x86_64-unknown-linux-gnu/llvm/bin/llvm-*`.

0 commit comments

Comments
 (0)