about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src/coverageinfo
AgeCommit message (Collapse)AuthorLines
2022-03-08add `#[rustc_pass_by_value]` to more typeslcnr-4/+4
2022-02-04Rollup merge of #90132 - joshtriplett:stabilize-instrument-coverage, ↵Matthias Krüger-2/+2
r=wesleywiser Stabilize `-Z instrument-coverage` as `-C instrument-coverage` (Tracking issue for `instrument-coverage`: https://github.com/rust-lang/rust/issues/79121) This PR stabilizes support for instrumentation-based code coverage, previously provided via the `-Z instrument-coverage` option. (Continue supporting `-Z instrument-coverage` for compatibility for now, but show a deprecation warning for it.) Many, many people have tested this support, and there are numerous reports of it working as expected. Move the documentation from the unstable book to stable rustc documentation. Update uses and documentation to use the `-C` option. Addressing questions raised in the tracking issue: > If/when stabilized, will the compiler flag be updated to -C instrument-coverage? (If so, the -Z variant could also be supported for some time, to ease migrations for existing users and scripts.) This stabilization PR updates the option to `-C` and keeps the `-Z` variant to ease migration. > The Rust coverage implementation depends on (and automatically turns on) -Z symbol-mangling-version=v0. Will stabilizing this feature depend on stabilizing v0 symbol-mangling first? If so, what is the current status and timeline? This stabilization PR depends on https://github.com/rust-lang/rust/pull/90128 , which stabilizes `-C symbol-mangling-version=v0` (but does not change the default symbol-mangling-version). > The Rust coverage implementation implements the latest version of LLVM's Coverage Mapping Format (version 4), which forces a dependency on LLVM 11 or later. A compiler error is generated if attempting to compile with coverage, and using an older version of LLVM. Given that LLVM 13 has now been released, requiring LLVM 11 for coverage support seems like a reasonable requirement. If people don't have at least LLVM 11, nothing else breaks; they just can't use coverage support. Given that coverage support currently requires a nightly compiler and LLVM 11 or newer, allowing it on a stable compiler built with LLVM 11 or newer seems like an improvement. The [tracking issue](https://github.com/rust-lang/rust/issues/79121) and the [issue label A-code-coverage](https://github.com/rust-lang/rust/labels/A-code-coverage) link to a few open issues related to `instrument-coverage`, but none of them seem like showstoppers. All of them seem like improvements and refinements we can make after stabilization. The original `-Z instrument-coverage` support went through a compiler-team MCP at https://github.com/rust-lang/compiler-team/issues/278 . Based on that, `@pnkfelix` suggested that this needed a stabilization PR and a compiler-team FCP.
2022-01-21Work around missing code coverage data causing llvm-cov failuresWesley Wiser-4/+13
If we do not add code coverage instrumentation to the `Body` of a function, then when we go to generate the function record for it, we won't write any data and this later causes llvm-cov to fail when processing data for the entire coverage report. I've identified two main cases where we do not currently add code coverage instrumentation to the `Body` of a function: 1. If the function has a single `BasicBlock` and it ends with a `TerminatorKind::Unreachable`. 2. If the function is created using a proc macro of some kind. For case 1, this typically not important as this most often occurs as the result of function definitions that take or return uninhabited types. These kinds of functions, by definition, cannot even be called so they logically should not be counted in code coverage statistics. For case 2, I haven't looked into this very much but I've noticed while testing this patch that (other than functions which are covered by case 1) the skipped function coverage debug message is occasionally triggered in large crate graphs by functions generated from a proc macro. This may have something to do with weird spans being generated by the proc macro but this is just a guess. I think it's reasonable to land this change since currently, we fail to generate *any* results from llvm-cov when a function has no coverage instrumentation applied to it. With this change, we get coverage data for all functions other than the two cases discussed above.
2022-01-01Stabilize -Z instrument-coverage as -C instrument-coverageJosh Triplett-2/+2
Continue supporting -Z instrument-coverage for compatibility for now, but show a deprecation warning for it. Update uses and documentation to use the -C option. Move the documentation from the unstable book to stable rustc documentation.
2021-12-27Address review commentsWesley Wiser-20/+27
2021-12-20[code coverage] Fix missing dead code in modules that are never calledWesley Wiser-83/+24
The issue here is that the logic used to determine which CGU to put the dead function stubs in doesn't handle cases where a module is never assigned to a CGU. The partitioning logic also caused issues in #85461 where inline functions were duplicated into multiple CGUs resulting in duplicate symbols. This commit fixes the issue by removing the complex logic used to assign dead code stubs to CGUs and replaces it with a much simplier model: we pick one CGU to hold all the dead code stubs. We pick a CGU which has exported items which increases the likelihood the linker won't throw away our dead functions and we pick the smallest to minimize the impact on compilation times for crates with very large CGUs. Fixes #86177 Fixes #85718 Fixes #79622
2021-12-16Remove `in_band_lifetimes` from `rustc_codegen_llvm`LegionMammal978-11/+11
See #91867 for more information.
2021-12-10Rollup merge of #91625 - est31:remove_indexes, r=oli-obkMatthias Krüger-2/+2
Remove redundant [..]s
2021-12-09Remove redundant [..]sest31-2/+2
2021-12-03code-cov: generate dead functions with private/default linkageWesley Wiser-2/+2
As discovered in #85461, the MSVC linker treats weak symbols slightly differently than unix-y linkers do. This causes link.exe to fail with LNK1227 "conflicting weak extern definition" where as other targets are able to link successfully. This changes the dead functions from being generated as weak/hidden to private/default which, as the LLVM reference says: > Global values with “private” linkage are only directly accessible by objects in the current module. In particular, linking code into a module with a private global value may cause the private to be renamed as necessary to avoid collisions. Because the symbol is private to the module, all references can be updated. This doesn’t show up in any symbol table in the object file. This fixes the conflicting weak symbols but doesn't address the reason *why* we have conflicting symbols for these dead functions. The test cases added in this commit contain a minimal repro of the fundamental issue which is that the logic used to decide what dead code functions should be codegen'd in the current CGU doesn't take into account that functions can be duplicated across multiple CGUs (for instance, in the case of `#[inline(always)]` functions). Fixing that is likely to be a more complex change (see https://github.com/rust-lang/rust/issues/85461#issuecomment-985005805). Fixes #85461
2021-11-30Add conditional support for coverage map version 6Rich Kadel-12/+33
This commit augments Swatinem's initial commit in uncommitted PR #90047, which was a great starting point, but did not fully support LLVM Coverage Mapping Format version 6. Version 6 requires adding the compilation directory when file paths are relative, and since Rustc coverage maps use relative paths, we should add the expected compilation directory entry. Note, however, that with the compilation directory, coverage reports from `llvm-cov show` can now report file names (when the report includes more than one file) with the full absolute path to the file. This would be a problem for test results, but the workaround (for the rust coverage tests) is to include an additional `llvm-cov show` parameter: `--compilation-dir=.`
2021-11-23Update CoverageMappingFormat Support to Version6Arpad Borsos-10/+10
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.
2021-10-01Fix clippy lintsGuillaume Gomez-5/+4
2021-09-18Querify `fn_abi_of_{fn_ptr,instance}`.Eduard-Mihai Burtescu-1/+1
2021-09-18ty::layout: replicate `layout_of` setup for `fn_abi_of_{fn_ptr,instance}`.Eduard-Mihai Burtescu-4/+3
2021-05-17Auto merge of #85178 - cjgillot:local-crate, r=oli-obkbors-3/+3
Remove CrateNum parameter for queries that only work on local crate The pervasive `CrateNum` parameter is a remnant of the multi-crate rustc idea. Using `()` as query key in those cases avoids having to worry about the validity of the query key.
2021-05-17rustc_codegen_ssa: append blocks to functions w/o creating a builder.Eduard-Mihai Burtescu-1/+2
2021-05-12Use () for codegen queries.Camille GILLOT-2/+2
2021-05-12Use () for mir_keys.Camille GILLOT-1/+1
2021-05-07Rollup merge of #84875 - richkadel:no-coverage-dont-check-unused, r=tmandryYuki Okushi-6/+2
Removes unneeded check of `#[no_coverage]` in mapgen There is an anticipated feature request to support a compiler flag that only adds coverage for specific files (or perhaps mods). As I thought about where that change would need to be supported, I realized that checking the attribute in mapgen (for unused functions) was unnecessary. The unused functions are only synthesized if they have MIR coverage, and functions with the `no_coverage` attribute will not have been instrumented with MIR coverage statements in the first place. New tests confirm this. Also, while adding tests, I updated resolved comments and FIXMEs in other tests, and expanded comments and tests on one remaining issue that is still not resolved. r? `@tmandry` cc: `@wesleywiser`
2021-05-06Removes unneeded check of `#[no_coverage]` in mapgenRich Kadel-6/+2
And adds tests to validate it still works. There is an anticipated feature request to support a compiler flag that only adds coverage for specific files (or perhaps mods). As I thought about where that change would need to be supported, I realized that checking the attribute in mapgen (for unused functions) was unnecessary. The unused functions are only synthesized if they have MIR coverage, and functions with the `no_coverage` attribute will not have been instrumented with MIR coverage statements in the first place. New tests confirm this. Also, while adding tests, I updated resolved comments and FIXMEs in other tests.
2021-05-06Update coverage docs and command line helpRich Kadel-1/+1
2021-04-27Derived Eq no longer shows uncoveredRich Kadel-0/+5
The Eq trait has a special hidden function. MIR `InstrumentCoverage` would add this function to the coverage map, but it is never called, so the `Eq` trait would always appear uncovered. Fixes: #83601 The fix required creating a new function attribute `no_coverage` to mark functions that should be ignored by `InstrumentCoverage` and the coverage `mapgen` (during codegen). While testing, I also noticed two other issues: * spanview debug file output ICEd on a function with no body. The workaround for this is included in this PR. * `assert_*!()` macro coverage can appear covered if followed by another `assert_*!()` macro. Normally they appear uncovered. I submitted a new Issue #84561, and added a coverage test to demonstrate this issue.
2021-04-02Translate counters from Rust 1-based to LLVM 0-based counter idsRich Kadel-6/+2
A colleague contacted me and asked why Rust's counters start at 1, when Clangs appear to start at 0. There is a reason why Rust's internal counters start at 1 (see the docs), and I tried to keep them consistent when codegenned to LLVM's coverage mapping format. LLVM should be tolerant of missing counters, but as my colleague pointed out, `llvm-cov` will silently fail to generate a coverage report for a function based on LLVM's assumption that the counters are 0-based. See: https://github.com/llvm/llvm-project/blob/main/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp#L170 Apparently, if, for example, a function has no branches, it would have exactly 1 counter. `CounterValues.size()` would be 1, and (with the 1-based index), the counter ID would be 1. This would fail the check and abort reporting coverage for the function. It turns out that by correcting for this during coverage map generation, by subtracting 1 from the Rust Counter ID (both when generating the counter increment intrinsic call, and when adding counters to the map), some uncovered functions (including in tests) now appear covered! This corrects the coverage for a few tests!
2021-03-23Changes from review commentsRich Kadel-3/+23
2021-03-23Change def_id filter to use requires_monomorphization()Rich Kadel-1/+1
Per @wesleywiser's comment: https://github.com/rust-lang/rust/pull/83307#discussion_r599223342
2021-03-19gave unused_fn WeakAnyLinkage; moved create_pgo_func_name_varRich Kadel-18/+19
The sample json5format tests produce coverage results again (and work with opt-level 3!)
2021-03-19coverage bug fixes and optimization supportRich Kadel-143/+226
Adjusted LLVM codegen for code compiled with `-Zinstrument-coverage` to address multiple, somewhat related issues. Fixed a significant flaw in prior coverage solution: Every counter generated a new counter variable, but there should have only been one counter variable per function. This appears to have bloated .profraw files significantly. (For a small program, it increased the size by about 40%. I have not tested large programs, but there is anecdotal evidence that profraw files were way too large. This is a good fix, regardless, but hopefully it also addresses related issues. Fixes: #82144 Invalid LLVM coverage data produced when compiled with -C opt-level=1 Existing tests now work up to at least `opt-level=3`. This required a detailed analysis of the LLVM IR, comparisons with Clang C++ LLVM IR when compiled with coverage, and a lot of trial and error with codegen adjustments. The biggest hurdle was figuring out how to continue to support coverage results for unused functions and generics. Rust's coverage results have three advantages over Clang's coverage results: 1. Rust's coverage map does not include any overlapping code regions, making coverage counting unambiguous. 2. Rust generates coverage results (showing zero counts) for all unused functions, including generics. (Clang does not generate coverage for uninstantiated template functions.) 3. Rust's unused functions produce minimal stubbed functions in LLVM IR, sufficient for including in the coverage results; while Clang must generate the complete LLVM IR for each unused function, even though it will never be called. This PR removes the previous hack of attempting to inject coverage into some other existing function instance, and generates dedicated instances for each unused function. This change, and a few other adjustments (similar to what is required for `-C link-dead-code`, but with lower impact), makes it possible to support LLVM optimizations. Fixes: #79651 Coverage report: "Unexecuted instantiation:..." for a generic function from multiple crates Fixed by removing the aforementioned hack. Some "Unexecuted instantiation" notices are unavoidable, as explained in the `used_crate.rs` test, but `-Zinstrument-coverage` has new options to back off support for either unused generics, or all unused functions, which avoids the notice, at the cost of less coverage of unused functions. Fixes: #82875 Invalid LLVM coverage data produced with crate brotli_decompressor Fixed by disabling the LLVM function attribute that forces inlining, if `-Z instrument-coverage` is enabled. This attribute is applied to Rust functions with `#[inline(always)], and in some cases, the forced inlining breaks coverage instrumentation and reports.
2021-03-15Functions inlined into reachable functions are reachableTomasz Miąsko-1/+1
Consider functions to be reachable for code coverage purposes, either when they reach the code generation directly, or indirectly as inlined part of another function.
2021-03-15Make source-based code coverage compatible with MIR inliningTomasz Miąsko-1/+1
When codegenning code coverage use the instance that coverage data was originally generated for, to ensure basic level of compatibility with MIR inlining.
2021-03-01Don't directly expose coverage::CounterMappingRegion via FFINikita Popov-2/+2
The definition of this struct changes in LLVM 12 due to the addition of branch coverage support. To avoid future mismatches, declare our own struct and then convert between them.
2021-01-03remove redundant closures (clippy::redundant_closure)Matthias Krüger-1/+1
2020-12-07Fixes to Rust coverageRich Kadel-1/+1
Fixes: #79725 Some macros can create a situation where `fn_sig_span` and `body_span` map to different files. New documentation on coverage tests incorrectly assumed multiple test binaries could just be listed at the end of the `llvm-cov` command, but it turns out each binary needs a `--object` prefix. This PR fixes the bug and updates the documentation to correct that issue. It also fixes a few other minor issues in internal implementation comments, and adds documentation on getting coverage results for doc tests.
2020-12-03Addressed feedback from 2020-12-01Rich Kadel-0/+19
Added one more test (two files) showing coverage of generics and unused functions across crates. Created and referenced new Issues, as requested. Added comments. Added a note about the possible effects of compiler options on LLVM coverage maps.
2020-12-03Combination of commitsRich Kadel-7/+148
Fixes multiple issue with counters, with simplification Includes a change to the implicit else span in ast_lowering, so coverage of the implicit else no longer spans the `then` block. Adds coverage for unused closures and async function bodies. Fixes: #78542 Adding unreachable regions for known MIR missing from coverage map Cleaned up PR commits, and removed link-dead-code requirement and tests Coverage no longer depends on Issue #76038 (`-C link-dead-code` is no longer needed or enforced, so MSVC can use the same tests as Linux and MacOS now) Restrict adding unreachable regions to covered files Improved the code that adds coverage for uncalled functions (with MIR but not-codegenned) to avoid generating coverage in files not already included in the files with covered functions. Resolved last known issue requiring --emit llvm-ir workaround Fixed bugs in how unreachable code spans were added.
2020-11-25Update compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rsRich Kadel-1/+1
2020-11-25replace assert with condition and `fatal` errorRich Kadel-1/+3
2020-11-25Improved version checkRich Kadel-7/+9
2020-11-24Apply suggestions from code reviewRich Kadel-1/+1
Co-authored-by: Wesley Wiser <wwiser@gmail.com>
2020-11-24Check for LLVM 11+ when using `-Z instrument-coverage`Rich Kadel-2/+2
* `rustc` should now compile under LLVM 9 or 10 * Compiler generates an error if `-Z instrument-coverage` is specified but LLVM version is less than 11 * Coverage tests that require `-Z instrument-coverage` and run codegen should be skipped if LLVM version is less than 11
2020-11-23Updated links to LLVM 11 docs and typesRich Kadel-3/+3
2020-11-23Upgrades the coverage map to Version 4Rich Kadel-112/+143
Changes the coverage map injected into binaries compiled with `-Zinstrument-coverage` to LLVM Coverage Mapping Format, Version 4 (from Version 3). Note, binaries compiled with this version will require LLVM tools from at least LLVM Version 11.
2020-11-05Addressed all feedback to dateRich Kadel-5/+3
2020-11-05Injecting expressions in place of counters where helpfulRich Kadel-4/+15
Implementing the Graph traits for the BasicCoverageBlock graph. optimized replacement of counters with expressions plus new BCB graphviz * Avoid adding coverage to unreachable blocks. * Special case for Goto at the end of the body. Make it non-reportable. Improved debugging and formatting options (from env) Don't automatically add counters to BCBs without CoverageSpans. They may still get counters but only if there are dependencies from other BCBs that have spans, I think. Make CodeRegions optional for Counters too. It is possible to inject counters (`llvm.instrprof.increment` intrinsic calls without corresponding code regions in the coverage map. An expression can still uses these counter values. Refactored instrument_coverage.rs -> instrument_coverage/mod.rs, and then broke up the mod into multiple files. Compiling with coverage, with the expression optimization, works on the json5format crate and its dependencies. Refactored debug features from mod.rs to debug.rs
2020-11-05Rust coverage before splitting instrument_coverage.rsRich Kadel-28/+38
2020-10-23Update compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rsRich Kadel-4/+4
Co-authored-by: Wesley Wiser <wwiser@gmail.com>
2020-10-23Make codegen coverage_context optional, and checkRich Kadel-33/+51
Addresses Issue #78286 Libraries compiled with coverage and linked with out enabling coverage would fail when attempting to add the library's coverage statements to the codegen coverage context (None). Now, if coverage statements are encountered while compiling / linking with `-Z instrument-coverage` disabled, codegen will *not* attempt to add code regions to a coverage map, and it will not inject the LLVM instrprof_increment intrinsic calls.
2020-10-05Updates to experimental coverage counter injectionRich Kadel-0/+1
This is a combination of 18 commits. Commit #2: Additional examples and some small improvements. Commit #3: fixed mir-opt non-mir extensions and spanview title elements Corrected a fairly recent assumption in runtest.rs that all MIR dump files end in .mir. (It was appending .mir to the graphviz .dot and spanview .html file names when generating blessed output files. That also left outdated files in the baseline alongside the files with the incorrect names, which I've now removed.) Updated spanview HTML title elements to match their content, replacing a hardcoded and incorrect name that was left in accidentally when originally submitted. Commit #4: added more test examples also improved Makefiles with support for non-zero exit status and to force validation of tests unless a specific test overrides it with a specific comment. Commit #5: Fixed rare issues after testing on real-world crate Commit #6: Addressed PR feedback, and removed temporary -Zexperimental-coverage -Zinstrument-coverage once again supports the latest capabilities of LLVM instrprof coverage instrumentation. Also fixed a bug in spanview. Commit #7: Fix closure handling, add tests for closures and inner items And cleaned up other tests for consistency, and to make it more clear where spans start/end by breaking up lines. Commit #8: renamed "typical" test results "expected" Now that the `llvm-cov show` tests are improved to normally expect matching actuals, and to allow individual tests to override that expectation. Commit #9: test coverage of inline generic struct function Commit #10: Addressed review feedback * Removed unnecessary Unreachable filter. * Replaced a match wildcard with remining variants. * Added more comments to help clarify the role of successors() in the CFG traversal Commit #11: refactoring based on feedback * refactored `fn coverage_spans()`. * changed the way I expand an empty coverage span to improve performance * fixed a typo that I had accidently left in, in visit.rs Commit #12: Optimized use of SourceMap and SourceFile Commit #13: Fixed a regression, and synched with upstream Some generated test file names changed due to some new change upstream. Commit #14: Stripping out crate disambiguators from demangled names These can vary depending on the test platform. Commit #15: Ignore llvm-cov show diff on test with generics, expand IO error message Tests with generics produce llvm-cov show results with demangled names that can include an unstable "crate disambiguator" (hex value). The value changes when run in the Rust CI Windows environment. I added a sed filter to strip them out (in a prior commit), but sed also appears to fail in the same environment. Until I can figure out a workaround, I'm just going to ignore this specific test result. I added a FIXME to follow up later, but it's not that critical. I also saw an error with Windows GNU, but the IO error did not specify a path for the directory or file that triggered the error. I updated the error messages to provide more info for next, time but also noticed some other tests with similar steps did not fail. Looks spurious. Commit #16: Modify rust-demangler to strip disambiguators by default Commit #17: Remove std::process::exit from coverage tests Due to Issue #77553, programs that call std::process::exit() do not generate coverage results on Windows MSVC. Commit #18: fix: test file paths exceeding Windows max path len
2020-08-30mv compiler to compiler/mark-0/+408