Remove support for -Zprofile (gcov-style coverage instrumentation)

This commit is contained in:
Zalathar 2024-10-17 20:11:20 +11:00
parent 759e07f063
commit ce3e14a448
15 changed files with 10 additions and 146 deletions

View File

@ -232,11 +232,6 @@ fn probestack_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
return None; return None;
} }
// probestack doesn't play nice either with gcov profiling.
if cx.sess().opts.unstable_opts.profile {
return None;
}
let attr_value = match cx.sess().target.stack_probes { let attr_value = match cx.sess().target.stack_probes {
StackProbeType::None => return None, StackProbeType::None => return None,
// Request LLVM to generate the probes inline. If the given LLVM version does not support // Request LLVM to generate the probes inline. If the given LLVM version does not support

View File

@ -591,7 +591,6 @@ pub(crate) unsafe fn llvm_optimize(
pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
config.instrument_coverage, config.instrument_coverage,
instr_profile_output_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), instr_profile_output_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
config.instrument_gcov,
pgo_sample_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), pgo_sample_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
config.debug_info_for_profiling, config.debug_info_for_profiling,
llvm_selfprofiler, llvm_selfprofiler,

View File

@ -7,7 +7,6 @@ use std::{iter, ptr};
use libc::{c_char, c_longlong, c_uint}; use libc::{c_char, c_longlong, c_uint};
use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo}; use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo};
use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::traits::*;
use rustc_fs_util::path_to_c_string;
use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::bug; use rustc_middle::bug;
@ -979,33 +978,8 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
debug_name_table_kind, debug_name_table_kind,
); );
if tcx.sess.opts.unstable_opts.profile {
let default_gcda_path = &output_filenames.with_extension("gcda");
let gcda_path =
tcx.sess.opts.unstable_opts.profile_emit.as_ref().unwrap_or(default_gcda_path);
let gcov_cu_info = [
path_to_mdstring(debug_context.llcontext, &output_filenames.with_extension("gcno")),
path_to_mdstring(debug_context.llcontext, gcda_path),
unit_metadata,
];
let gcov_metadata = llvm::LLVMMDNodeInContext2(
debug_context.llcontext,
gcov_cu_info.as_ptr(),
gcov_cu_info.len(),
);
let val = llvm::LLVMMetadataAsValue(debug_context.llcontext, gcov_metadata);
llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, c"llvm.gcov".as_ptr(), val);
}
return unit_metadata; return unit_metadata;
}; };
fn path_to_mdstring<'ll>(llcx: &'ll llvm::Context, path: &Path) -> &'ll llvm::Metadata {
let path_str = path_to_c_string(path);
unsafe { llvm::LLVMMDStringInContext2(llcx, path_str.as_ptr(), path_str.as_bytes().len()) }
}
} }
/// Creates a `DW_TAG_member` entry inside the DIE represented by the given `type_di_node`. /// Creates a `DW_TAG_member` entry inside the DIE represented by the given `type_di_node`.

View File

@ -55,7 +55,6 @@ const DW_TAG_arg_variable: c_uint = 0x101;
/// A context object for maintaining all state needed by the debuginfo module. /// A context object for maintaining all state needed by the debuginfo module.
pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> { pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> {
llcontext: &'ll llvm::Context,
llmod: &'ll llvm::Module, llmod: &'ll llvm::Module,
builder: &'ll mut DIBuilder<'ll>, builder: &'ll mut DIBuilder<'ll>,
created_files: RefCell<UnordMap<Option<(StableSourceFileId, SourceFileHash)>, &'ll DIFile>>, created_files: RefCell<UnordMap<Option<(StableSourceFileId, SourceFileHash)>, &'ll DIFile>>,
@ -78,9 +77,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
debug!("CodegenUnitDebugContext::new"); debug!("CodegenUnitDebugContext::new");
let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) }; let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) };
// DIBuilder inherits context from the module, so we'd better use the same one // DIBuilder inherits context from the module, so we'd better use the same one
let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
CodegenUnitDebugContext { CodegenUnitDebugContext {
llcontext,
llmod, llmod,
builder, builder,
created_files: Default::default(), created_files: Default::default(),

View File

@ -2269,7 +2269,6 @@ unsafe extern "C" {
PGOUsePath: *const c_char, PGOUsePath: *const c_char,
InstrumentCoverage: bool, InstrumentCoverage: bool,
InstrProfileOutput: *const c_char, InstrProfileOutput: *const c_char,
InstrumentGCOV: bool,
PGOSampleUsePath: *const c_char, PGOSampleUsePath: *const c_char,
DebugInfoForProfiling: bool, DebugInfoForProfiling: bool,
llvm_selfprofiler: *mut c_void, llvm_selfprofiler: *mut c_void,

View File

@ -90,7 +90,6 @@ pub struct ModuleConfig {
pub pgo_sample_use: Option<PathBuf>, pub pgo_sample_use: Option<PathBuf>,
pub debug_info_for_profiling: bool, pub debug_info_for_profiling: bool,
pub instrument_coverage: bool, pub instrument_coverage: bool,
pub instrument_gcov: bool,
pub sanitizer: SanitizerSet, pub sanitizer: SanitizerSet,
pub sanitizer_recover: SanitizerSet, pub sanitizer_recover: SanitizerSet,
@ -123,12 +122,7 @@ pub struct ModuleConfig {
} }
impl ModuleConfig { impl ModuleConfig {
fn new( fn new(kind: ModuleKind, tcx: TyCtxt<'_>, no_builtins: bool) -> ModuleConfig {
kind: ModuleKind,
tcx: TyCtxt<'_>,
no_builtins: bool,
is_compiler_builtins: bool,
) -> ModuleConfig {
// If it's a regular module, use `$regular`, otherwise use `$other`. // If it's a regular module, use `$regular`, otherwise use `$other`.
// `$regular` and `$other` are evaluated lazily. // `$regular` and `$other` are evaluated lazily.
macro_rules! if_regular { macro_rules! if_regular {
@ -189,13 +183,6 @@ impl ModuleConfig {
pgo_sample_use: if_regular!(sess.opts.unstable_opts.profile_sample_use.clone(), None), pgo_sample_use: if_regular!(sess.opts.unstable_opts.profile_sample_use.clone(), None),
debug_info_for_profiling: sess.opts.unstable_opts.debug_info_for_profiling, debug_info_for_profiling: sess.opts.unstable_opts.debug_info_for_profiling,
instrument_coverage: if_regular!(sess.instrument_coverage(), false), instrument_coverage: if_regular!(sess.instrument_coverage(), false),
instrument_gcov: if_regular!(
// compiler_builtins overrides the codegen-units settings,
// which is incompatible with -Zprofile which requires that
// only a single codegen unit is used per crate.
sess.opts.unstable_opts.profile && !is_compiler_builtins,
false
),
sanitizer: if_regular!(sess.opts.unstable_opts.sanitizer, SanitizerSet::empty()), sanitizer: if_regular!(sess.opts.unstable_opts.sanitizer, SanitizerSet::empty()),
sanitizer_dataflow_abilist: if_regular!( sanitizer_dataflow_abilist: if_regular!(
@ -473,16 +460,12 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID); let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins); let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins);
let is_compiler_builtins = attr::contains_name(crate_attrs, sym::compiler_builtins);
let crate_info = CrateInfo::new(tcx, target_cpu); let crate_info = CrateInfo::new(tcx, target_cpu);
let regular_config = let regular_config = ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins);
ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins, is_compiler_builtins); let metadata_config = ModuleConfig::new(ModuleKind::Metadata, tcx, no_builtins);
let metadata_config = let allocator_config = ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins);
ModuleConfig::new(ModuleKind::Metadata, tcx, no_builtins, is_compiler_builtins);
let allocator_config =
ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins, is_compiler_builtins);
let (shared_emitter, shared_emitter_main) = SharedEmitter::new(); let (shared_emitter, shared_emitter_main) = SharedEmitter::new();
let (codegen_worker_send, codegen_worker_receive) = channel(); let (codegen_worker_send, codegen_worker_receive) = channel();

View File

@ -832,8 +832,6 @@ fn test_unstable_options_tracking_hash() {
tracked!(polonius, Polonius::Legacy); tracked!(polonius, Polonius::Legacy);
tracked!(precise_enum_drop_elaboration, false); tracked!(precise_enum_drop_elaboration, false);
tracked!(print_fuel, Some("abc".to_string())); tracked!(print_fuel, Some("abc".to_string()));
tracked!(profile, true);
tracked!(profile_emit, Some(PathBuf::from("abc")));
tracked!(profile_sample_use, Some(PathBuf::from("abc"))); tracked!(profile_sample_use, Some(PathBuf::from("abc")));
tracked!(profiler_runtime, "abc".to_string()); tracked!(profiler_runtime, "abc".to_string());
tracked!(regparm, Some(3)); tracked!(regparm, Some(3));

View File

@ -42,7 +42,6 @@
#if LLVM_VERSION_GE(19, 0) #if LLVM_VERSION_GE(19, 0)
#include "llvm/Support/PGOOptions.h" #include "llvm/Support/PGOOptions.h"
#endif #endif
#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h" #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
#include "llvm/Transforms/Instrumentation/InstrProfiling.h" #include "llvm/Transforms/Instrumentation/InstrProfiling.h"
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h" #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
@ -714,9 +713,8 @@ extern "C" LLVMRustResult LLVMRustOptimize(
bool SLPVectorize, bool LoopVectorize, bool DisableSimplifyLibCalls, bool SLPVectorize, bool LoopVectorize, bool DisableSimplifyLibCalls,
bool EmitLifetimeMarkers, LLVMRustSanitizerOptions *SanitizerOptions, bool EmitLifetimeMarkers, LLVMRustSanitizerOptions *SanitizerOptions,
const char *PGOGenPath, const char *PGOUsePath, bool InstrumentCoverage, const char *PGOGenPath, const char *PGOUsePath, bool InstrumentCoverage,
const char *InstrProfileOutput, bool InstrumentGCOV, const char *InstrProfileOutput, const char *PGOSampleUsePath,
const char *PGOSampleUsePath, bool DebugInfoForProfiling, bool DebugInfoForProfiling, void *LlvmSelfProfiler,
void *LlvmSelfProfiler,
LLVMRustSelfProfileBeforePassCallback BeforePassCallback, LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
LLVMRustSelfProfileAfterPassCallback AfterPassCallback, LLVMRustSelfProfileAfterPassCallback AfterPassCallback,
const char *ExtraPasses, size_t ExtraPassesLen, const char *LLVMPlugins, const char *ExtraPasses, size_t ExtraPassesLen, const char *LLVMPlugins,
@ -847,13 +845,6 @@ extern "C" LLVMRustResult LLVMRustOptimize(
}); });
} }
if (InstrumentGCOV) {
PipelineStartEPCallbacks.push_back(
[](ModulePassManager &MPM, OptimizationLevel Level) {
MPM.addPass(GCOVProfilerPass(GCOVOptions::getDefault()));
});
}
if (InstrumentCoverage) { if (InstrumentCoverage) {
PipelineStartEPCallbacks.push_back( PipelineStartEPCallbacks.push_back(
[InstrProfileOutput](ModulePassManager &MPM, OptimizationLevel Level) { [InstrProfileOutput](ModulePassManager &MPM, OptimizationLevel Level) {

View File

@ -778,9 +778,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
fn inject_profiler_runtime(&mut self, krate: &ast::Crate) { fn inject_profiler_runtime(&mut self, krate: &ast::Crate) {
if self.sess.opts.unstable_opts.no_profiler_runtime if self.sess.opts.unstable_opts.no_profiler_runtime
|| !(self.sess.instrument_coverage() || !(self.sess.instrument_coverage() || self.sess.opts.cg.profile_generate.enabled())
|| self.sess.opts.unstable_opts.profile
|| self.sess.opts.cg.profile_generate.enabled())
{ {
return; return;
} }

View File

@ -2453,7 +2453,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
let output_types = parse_output_types(early_dcx, &unstable_opts, matches); let output_types = parse_output_types(early_dcx, &unstable_opts, matches);
let mut cg = CodegenOptions::build(early_dcx, matches); let mut cg = CodegenOptions::build(early_dcx, matches);
let (disable_local_thinlto, mut codegen_units) = should_override_cgus_and_disable_thinlto( let (disable_local_thinlto, codegen_units) = should_override_cgus_and_disable_thinlto(
early_dcx, early_dcx,
&output_types, &output_types,
matches, matches,
@ -2476,18 +2476,6 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
let assert_incr_state = parse_assert_incr_state(early_dcx, &unstable_opts.assert_incr_state); let assert_incr_state = parse_assert_incr_state(early_dcx, &unstable_opts.assert_incr_state);
if unstable_opts.profile && incremental.is_some() {
early_dcx.early_fatal("can't instrument with gcov profiling when compiling incrementally");
}
if unstable_opts.profile {
match codegen_units {
Some(1) => {}
None => codegen_units = Some(1),
Some(_) => early_dcx
.early_fatal("can't instrument with gcov profiling with multiple codegen units"),
}
}
if cg.profile_generate.enabled() && cg.profile_use.is_some() { if cg.profile_generate.enabled() && cg.profile_use.is_some() {
early_dcx.early_fatal("options `-C profile-generate` and `-C profile-use` are exclusive"); early_dcx.early_fatal("options `-C profile-generate` and `-C profile-use` are exclusive");
} }

View File

@ -1985,13 +1985,8 @@ options! {
proc_macro_execution_strategy: ProcMacroExecutionStrategy = (ProcMacroExecutionStrategy::SameThread, proc_macro_execution_strategy: ProcMacroExecutionStrategy = (ProcMacroExecutionStrategy::SameThread,
parse_proc_macro_execution_strategy, [UNTRACKED], parse_proc_macro_execution_strategy, [UNTRACKED],
"how to run proc-macro code (default: same-thread)"), "how to run proc-macro code (default: same-thread)"),
profile: bool = (false, parse_bool, [TRACKED],
"insert profiling code (default: no)"),
profile_closures: bool = (false, parse_no_flag, [UNTRACKED], profile_closures: bool = (false, parse_no_flag, [UNTRACKED],
"profile size of closures"), "profile size of closures"),
profile_emit: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
"file path to emit profiling data at runtime when using 'profile' \
(default based on relative source path)"),
profile_sample_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED], profile_sample_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
"use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO)"), "use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO)"),
profiler_runtime: String = (String::from("profiler_builtins"), parse_string, [TRACKED], profiler_runtime: String = (String::from("profiler_builtins"), parse_string, [TRACKED],

View File

@ -2,12 +2,8 @@
## Introduction ## Introduction
The Rust compiler includes two code coverage implementations: This document describes how to enable and use LLVM instrumentation-based coverage,
via the `-C instrument-coverage` compiler flag.
- A GCC-compatible, gcov-based coverage implementation, enabled with `-Z profile`, which derives coverage data based on DebugInfo.
- A source-based code coverage implementation, enabled with `-C instrument-coverage`, which uses LLVM's native, efficient coverage instrumentation to generate very precise coverage data.
This document describes how to enable and use the LLVM instrumentation-based coverage, via the `-C instrument-coverage` compiler flag.
## How it works ## How it works

View File

@ -1,27 +0,0 @@
# `profile`
The tracking issue for this feature is: [#42524](https://github.com/rust-lang/rust/issues/42524).
------------------------
This feature allows the generation of code coverage reports.
Set the `-Zprofile` compiler flag in order to enable gcov profiling.
For example:
```Bash
cargo new testgcov --bin
cd testgcov
export RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
export CARGO_INCREMENTAL=0
cargo build
cargo run
```
Once you've built and run your program, files with the `gcno` (after build) and `gcda` (after execution) extensions will be created.
You can parse them with [llvm-cov gcov](https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-gcov) or [grcov](https://github.com/mozilla/grcov).
Please note that `RUSTFLAGS` by default applies to everything that cargo builds and runs during a build!
When the `--target` flag is explicitly passed to cargo, the `RUSTFLAGS` no longer apply to build scripts and procedural macros.
For more fine-grained control consider passing a `RUSTC_WRAPPER` program to cargo that only adds the profiling flags to
rustc for the specific crates you want to profile.

View File

@ -1,21 +0,0 @@
// This test revolves around the rustc flag -Z profile, which should
// generate a .gcno file (initial profiling information) as well
// as a .gcda file (branch counters). The path where these are emitted
// should also be configurable with -Z profile-emit. This test checks
// that the files are produced, and then that the latter flag is respected.
// See https://github.com/rust-lang/rust/pull/42433
//@ ignore-cross-compile
//@ needs-profiler-runtime
use run_make_support::{path, run, rustc};
fn main() {
rustc().arg("-g").arg("-Zprofile").input("test.rs").run();
run("test");
assert!(path("test.gcno").exists(), "no .gcno file");
assert!(path("test.gcda").exists(), "no .gcda file");
rustc().arg("-g").arg("-Zprofile").arg("-Zprofile-emit=abc/abc.gcda").input("test.rs").run();
run("test");
assert!(path("abc/abc.gcda").exists(), "gcda file not emitted to defined path");
}

View File

@ -1 +0,0 @@
fn main() {}