tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Zprofile-1.92.patch (18535B)


      1 This reverts
      2 https://github.com/rust-lang/rust/commit/659e20fa7524f8fd217476daf5ecbbe366b2ae61
      3 and
      4 https://github.com/rust-lang/rust/pull/131829
      5 
      6 to restore support for -Zprofile (gcov-style coverage) that was removed from
      7 rustc 1.84.0
      8 
      9 diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
     10 index a25ce9e5a90..5fb2f7d7e7b 100644
     11 --- a/compiler/rustc_codegen_llvm/src/attributes.rs
     12 +++ b/compiler/rustc_codegen_llvm/src/attributes.rs
     13 @@ -269,6 +269,11 @@ fn probestack_attr<'ll, 'tcx>(cx: &SimpleCx<'ll>, tcx: TyCtxt<'tcx>) -> Option<&
     14         return None;
     15     }
     16 
     17 +    // probestack doesn't play nice either with gcov profiling.
     18 +    if tcx.sess.opts.unstable_opts.profile {
     19 +        return None;
     20 +    }
     21 +
     22     let attr_value = match tcx.sess.target.stack_probes {
     23         StackProbeType::None => return None,
     24         // Request LLVM to generate the probes inline. If the given LLVM version does not support
     25 diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
     26 index d87de8b3846..46c57f22f34 100644
     27 --- a/compiler/rustc_codegen_llvm/src/back/write.rs
     28 +++ b/compiler/rustc_codegen_llvm/src/back/write.rs
     29 @@ -762,6 +762,7 @@ fn handle_offload<'ll>(cx: &'ll SimpleCx<'_>, old_fn: &llvm::Value) {
     30             pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
     31             config.instrument_coverage,
     32             instr_profile_output_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
     33 +            config.instrument_gcov,
     34             pgo_sample_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
     35             config.debug_info_for_profiling,
     36             llvm_selfprofiler,
     37 diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
     38 index dc941cb41c5..e6757d5b981 100644
     39 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
     40 +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
     41 @@ -1,7 +1,7 @@
     42 use std::borrow::Cow;
     43 use std::fmt::{self, Write};
     44 use std::hash::{Hash, Hasher};
     45 -use std::path::PathBuf;
     46 +use std::path::{Path, PathBuf};
     47 use std::sync::Arc;
     48 use std::{iter, ptr};
     49 
     50 @@ -9,6 +9,7 @@
     51 use rustc_abi::{Align, Size};
     52 use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo};
     53 use rustc_codegen_ssa::traits::*;
     54 +use rustc_fs_util::path_to_c_string;
     55 use rustc_hir::def::{CtorKind, DefKind};
     56 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
     57 use rustc_middle::bug;
     58 @@ -939,8 +940,33 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
     59             debug_name_table_kind,
     60         );
     61 
     62 +        if tcx.sess.opts.unstable_opts.profile {
     63 +            let default_gcda_path = &output_filenames.with_extension("gcda");
     64 +            let gcda_path =
     65 +                tcx.sess.opts.unstable_opts.profile_emit.as_ref().unwrap_or(default_gcda_path);
     66 +
     67 +            let gcov_cu_info = [
     68 +                path_to_mdstring(debug_context.llcontext, &output_filenames.with_extension("gcno")),
     69 +                path_to_mdstring(debug_context.llcontext, gcda_path),
     70 +                unit_metadata,
     71 +            ];
     72 +            let gcov_metadata = llvm::LLVMMDNodeInContext2(
     73 +                debug_context.llcontext,
     74 +                gcov_cu_info.as_ptr(),
     75 +                gcov_cu_info.len(),
     76 +            );
     77 +            let val = llvm::LLVMMetadataAsValue(debug_context.llcontext, gcov_metadata);
     78 +
     79 +            llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, c"llvm.gcov".as_ptr(), val);
     80 +        }
     81 +
     82         return unit_metadata;
     83     };
     84 +
     85 +    fn path_to_mdstring<'ll>(llcx: &'ll llvm::Context, path: &Path) -> &'ll llvm::Metadata {
     86 +        let path_str = path_to_c_string(path);
     87 +        unsafe { llvm::LLVMMDStringInContext2(llcx, path_str.as_ptr(), path_str.as_bytes().len()) }
     88 +    }
     89 }
     90 
     91 /// Creates a `DW_TAG_member` entry inside the DIE represented by the given `type_di_node`.
     92 diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
     93 index 1c63bbcd171..74f563e7470 100644
     94 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
     95 +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
     96 @@ -55,6 +55,7 @@
     97 
     98 /// A context object for maintaining all state needed by the debuginfo module.
     99 pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> {
    100 +    llcontext: &'ll llvm::Context,
    101     llmod: &'ll llvm::Module,
    102     builder: DIBuilderBox<'ll>,
    103     created_files: RefCell<UnordMap<Option<(StableSourceFileId, SourceFileHash)>, &'ll DIFile>>,
    104 @@ -70,7 +71,9 @@ pub(crate) fn new(llmod: &'ll llvm::Module) -> Self {
    105         debug!("CodegenUnitDebugContext::new");
    106         let builder = DIBuilderBox::new(llmod);
    107         // DIBuilder inherits context from the module, so we'd better use the same one
    108 +        let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
    109         CodegenUnitDebugContext {
    110 +            llcontext,
    111             llmod,
    112             builder,
    113             created_files: Default::default(),
    114 diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
    115 index 75b3e5955b7..0e7c703777a 100644
    116 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
    117 +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
    118 @@ -876,6 +876,7 @@ pub(crate) fn LLVMModuleCreateWithNameInContext(
    119         ModuleID: *const c_char,
    120         C: &Context,
    121     ) -> &Module;
    122 +    pub(crate) fn LLVMGetModuleContext(M: &Module) -> &Context;
    123     pub(crate) safe fn LLVMCloneModule(M: &Module) -> &Module;
    124 
    125     /// Data layout. See Module::getDataLayout.
    126 @@ -2382,6 +2383,7 @@ pub(crate) fn LLVMRustOptimize<'a>(
    127         PGOUsePath: *const c_char,
    128         InstrumentCoverage: bool,
    129         InstrProfileOutput: *const c_char,
    130 +        InstrumentGCOV: bool,
    131         PGOSampleUsePath: *const c_char,
    132         DebugInfoForProfiling: bool,
    133         llvm_selfprofiler: *mut c_void,
    134 diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
    135 index 3e36bd8552b..e64a0110a08 100644
    136 --- a/compiler/rustc_codegen_ssa/src/back/write.rs
    137 +++ b/compiler/rustc_codegen_ssa/src/back/write.rs
    138 @@ -84,6 +84,7 @@ pub struct ModuleConfig {
    139     pub pgo_sample_use: Option<PathBuf>,
    140     pub debug_info_for_profiling: bool,
    141     pub instrument_coverage: bool,
    142 +    pub instrument_gcov: bool,
    143 
    144     pub sanitizer: SanitizerSet,
    145     pub sanitizer_recover: SanitizerSet,
    146 @@ -116,7 +117,12 @@ pub struct ModuleConfig {
    147 }
    148 
    149 impl ModuleConfig {
    150 -    fn new(kind: ModuleKind, tcx: TyCtxt<'_>, no_builtins: bool) -> ModuleConfig {
    151 +    fn new(
    152 +        kind: ModuleKind,
    153 +        tcx: TyCtxt<'_>,
    154 +        no_builtins: bool,
    155 +        is_compiler_builtins: bool,
    156 +    ) -> ModuleConfig {
    157         // If it's a regular module, use `$regular`, otherwise use `$other`.
    158         // `$regular` and `$other` are evaluated lazily.
    159         macro_rules! if_regular {
    160 @@ -175,6 +181,13 @@ macro_rules! if_regular {
    161             pgo_sample_use: if_regular!(sess.opts.unstable_opts.profile_sample_use.clone(), None),
    162             debug_info_for_profiling: sess.opts.unstable_opts.debug_info_for_profiling,
    163             instrument_coverage: if_regular!(sess.instrument_coverage(), false),
    164 +            instrument_gcov: if_regular!(
    165 +                // compiler_builtins overrides the codegen-units settings,
    166 +                // which is incompatible with -Zprofile which requires that
    167 +                // only a single codegen unit is used per crate.
    168 +                sess.opts.unstable_opts.profile && !is_compiler_builtins,
    169 +                false
    170 +            ),
    171 
    172             sanitizer: if_regular!(sess.sanitizers(), SanitizerSet::empty()),
    173             sanitizer_dataflow_abilist: if_regular!(
    174 @@ -436,11 +449,14 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
    175 
    176     let crate_attrs = tcx.hir_attrs(rustc_hir::CRATE_HIR_ID);
    177     let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins);
    178 +    let is_compiler_builtins = attr::contains_name(crate_attrs, sym::compiler_builtins);
    179 
    180     let crate_info = CrateInfo::new(tcx, target_cpu);
    181 
    182 -    let regular_config = ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins);
    183 -    let allocator_config = ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins);
    184 +    let regular_config =
    185 +        ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins, is_compiler_builtins);
    186 +    let allocator_config =
    187 +        ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins, is_compiler_builtins);
    188 
    189     let (shared_emitter, shared_emitter_main) = SharedEmitter::new();
    190     let (codegen_worker_send, codegen_worker_receive) = channel();
    191 diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
    192 index d075f94ef85..01cf5d63bff 100644
    193 --- a/compiler/rustc_interface/src/tests.rs
    194 +++ b/compiler/rustc_interface/src/tests.rs
    195 @@ -851,6 +851,8 @@ macro_rules! tracked {
    196     tracked!(plt, Some(true));
    197     tracked!(polonius, Polonius::Legacy);
    198     tracked!(precise_enum_drop_elaboration, false);
    199 +    tracked!(profile, true);
    200 +    tracked!(profile_emit, Some(PathBuf::from("abc")));
    201     tracked!(profile_sample_use, Some(PathBuf::from("abc")));
    202     tracked!(profiler_runtime, "abc".to_string());
    203     tracked!(reg_struct_return, true);
    204 diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
    205 index 95cbec1b37b..10507f5bd51 100644
    206 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
    207 +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
    208 @@ -38,6 +38,7 @@
    209 #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
    210 #include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
    211 #include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
    212 +#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
    213 #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
    214 #include "llvm/Transforms/Instrumentation/InstrProfiling.h"
    215 #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
    216 @@ -564,8 +565,9 @@ extern "C" LLVMRustResult LLVMRustOptimize(
    217     bool PrintBeforeEnzyme, bool PrintAfterEnzyme, bool PrintPasses,
    218     LLVMRustSanitizerOptions *SanitizerOptions, const char *PGOGenPath,
    219     const char *PGOUsePath, bool InstrumentCoverage,
    220 -    const char *InstrProfileOutput, const char *PGOSampleUsePath,
    221 -    bool DebugInfoForProfiling, void *LlvmSelfProfiler,
    222 +    const char *InstrProfileOutput, bool InstrumentGCOV,
    223 +    const char *PGOSampleUsePath, bool DebugInfoForProfiling,
    224 +    void *LlvmSelfProfiler,
    225     LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
    226     LLVMRustSelfProfileAfterPassCallback AfterPassCallback,
    227     const char *ExtraPasses, size_t ExtraPassesLen, const char *LLVMPlugins,
    228 @@ -707,6 +709,13 @@ extern "C" LLVMRustResult LLVMRustOptimize(
    229     });
    230   }
    231 
    232 +  if (InstrumentGCOV) {
    233 +    PipelineStartEPCallbacks.push_back(
    234 +        [](ModulePassManager &MPM, OptimizationLevel Level) {
    235 +          MPM.addPass(GCOVProfilerPass(GCOVOptions::getDefault()));
    236 +        });
    237 +  }
    238 +
    239   if (InstrumentCoverage) {
    240     PipelineStartEPCallbacks.push_back(
    241         [InstrProfileOutput](ModulePassManager &MPM, OptimizationLevel Level) {
    242 diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
    243 index 4000f12459a..dfceb47a1af 100644
    244 --- a/compiler/rustc_metadata/src/creader.rs
    245 +++ b/compiler/rustc_metadata/src/creader.rs
    246 @@ -1003,7 +1003,7 @@ fn inject_panic_runtime(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) {
    247 
    248     fn inject_profiler_runtime(&mut self, tcx: TyCtxt<'_>) {
    249         let needs_profiler_runtime =
    250 -            tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled();
    251 +            tcx.sess.instrument_coverage() || tcx.sess.opts.unstable_opts.profile || tcx.sess.opts.cg.profile_generate.enabled();
    252         if !needs_profiler_runtime || tcx.sess.opts.unstable_opts.no_profiler_runtime {
    253             return;
    254         }
    255 diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
    256 index f326442c087..0750a085672 100644
    257 --- a/compiler/rustc_session/src/config.rs
    258 +++ b/compiler/rustc_session/src/config.rs
    259 @@ -2473,7 +2473,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
    260     let output_types = parse_output_types(early_dcx, &unstable_opts, matches);
    261 
    262     let mut cg = CodegenOptions::build(early_dcx, matches, &mut target_modifiers);
    263 -    let (disable_local_thinlto, codegen_units) = should_override_cgus_and_disable_thinlto(
    264 +    let (disable_local_thinlto, mut codegen_units) = should_override_cgus_and_disable_thinlto(
    265         early_dcx,
    266         &output_types,
    267         matches,
    268 @@ -2492,6 +2492,18 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
    269 
    270     let assert_incr_state = parse_assert_incr_state(early_dcx, &unstable_opts.assert_incr_state);
    271 
    272 +    if unstable_opts.profile && incremental.is_some() {
    273 +        early_dcx.early_fatal("can't instrument with gcov profiling when compiling incrementally");
    274 +    }
    275 +    if unstable_opts.profile {
    276 +        match codegen_units {
    277 +            Some(1) => {}
    278 +            None => codegen_units = Some(1),
    279 +            Some(_) => early_dcx
    280 +                .early_fatal("can't instrument with gcov profiling with multiple codegen units"),
    281 +        }
    282 +    }
    283 +
    284     if cg.profile_generate.enabled() && cg.profile_use.is_some() {
    285         early_dcx.early_fatal("options `-C profile-generate` and `-C profile-use` are exclusive");
    286     }
    287 diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
    288 index 2b83d1225c9..7b940cbfeee 100644
    289 --- a/compiler/rustc_session/src/options.rs
    290 +++ b/compiler/rustc_session/src/options.rs
    291 @@ -2581,8 +2581,13 @@ pub(crate) fn parse_align(slot: &mut Option<Align>, v: Option<&str>) -> bool {
    292     proc_macro_execution_strategy: ProcMacroExecutionStrategy = (ProcMacroExecutionStrategy::SameThread,
    293         parse_proc_macro_execution_strategy, [UNTRACKED],
    294         "how to run proc-macro code (default: same-thread)"),
    295 +    profile: bool = (false, parse_bool, [TRACKED],
    296 +        "insert profiling code (default: no)"),
    297     profile_closures: bool = (false, parse_no_value, [UNTRACKED],
    298         "profile size of closures"),
    299 +    profile_emit: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
    300 +        "file path to emit profiling data at runtime when using 'profile' \
    301 +        (default based on relative source path)"),
    302     profile_sample_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
    303         "use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO)"),
    304     profiler_runtime: String = (String::from("profiler_builtins"), parse_string, [TRACKED],
    305 diff --git a/src/doc/rustc/src/instrument-coverage.md b/src/doc/rustc/src/instrument-coverage.md
    306 index 57679f82f48..0f88bec2c71 100644
    307 --- a/src/doc/rustc/src/instrument-coverage.md
    308 +++ b/src/doc/rustc/src/instrument-coverage.md
    309 @@ -2,8 +2,12 @@
    310 
    311 ## Introduction
    312 
    313 -This document describes how to enable and use LLVM instrumentation-based coverage,
    314 -via the `-C instrument-coverage` compiler flag.
    315 +The Rust compiler includes two code coverage implementations:
    316 +
    317 +-   A GCC-compatible, gcov-based coverage implementation, enabled with `-Z profile`, which derives coverage data based on DebugInfo.
    318 +-   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.
    319 +
    320 +This document describes how to enable and use the LLVM instrumentation-based coverage, via the `-C instrument-coverage` compiler flag.
    321 
    322 ## How it works
    323 
    324 diff --git a/src/doc/unstable-book/src/compiler-flags/profile.md b/src/doc/unstable-book/src/compiler-flags/profile.md
    325 new file mode 100644
    326 index 00000000000..71303bfaff2
    327 --- /dev/null
    328 +++ b/src/doc/unstable-book/src/compiler-flags/profile.md
    329 @@ -0,0 +1,27 @@
    330 +# `profile`
    331 +
    332 +The tracking issue for this feature is: [#42524](https://github.com/rust-lang/rust/issues/42524).
    333 +
    334 +------------------------
    335 +
    336 +This feature allows the generation of code coverage reports.
    337 +
    338 +Set the `-Zprofile` compiler flag in order to enable gcov profiling.
    339 +
    340 +For example:
    341 +```Bash
    342 +cargo new testgcov --bin
    343 +cd testgcov
    344 +export RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
    345 +export CARGO_INCREMENTAL=0
    346 +cargo build
    347 +cargo run
    348 +```
    349 +
    350 +Once you've built and run your program, files with the `gcno` (after build) and `gcda` (after execution) extensions will be created.
    351 +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).
    352 +
    353 +Please note that `RUSTFLAGS` by default applies to everything that cargo builds and runs during a build!
    354 +When the `--target` flag is explicitly passed to cargo, the `RUSTFLAGS` no longer apply to build scripts and procedural macros.
    355 +For more fine-grained control consider passing a `RUSTC_WRAPPER` program to cargo that only adds the profiling flags to
    356 +rustc for the specific crates you want to profile.
    357 diff --git a/tests/run-make/profile/rmake.rs b/tests/run-make/profile/rmake.rs
    358 new file mode 100644
    359 index 00000000000..58a1b53c040
    360 --- /dev/null
    361 +++ b/tests/run-make/profile/rmake.rs
    362 @@ -0,0 +1,21 @@
    363 +// This test revolves around the rustc flag -Z profile, which should
    364 +// generate a .gcno file (initial profiling information) as well
    365 +// as a .gcda file (branch counters). The path where these are emitted
    366 +// should also be configurable with -Z profile-emit. This test checks
    367 +// that the files are produced, and then that the latter flag is respected.
    368 +// See https://github.com/rust-lang/rust/pull/42433
    369 +
    370 +//@ ignore-cross-compile
    371 +//@ needs-profiler-runtime
    372 +
    373 +use run_make_support::{path, run, rustc};
    374 +
    375 +fn main() {
    376 +    rustc().arg("-g").arg("-Zprofile").input("test.rs").run();
    377 +    run("test");
    378 +    assert!(path("test.gcno").exists(), "no .gcno file");
    379 +    assert!(path("test.gcda").exists(), "no .gcda file");
    380 +    rustc().arg("-g").arg("-Zprofile").arg("-Zprofile-emit=abc/abc.gcda").input("test.rs").run();
    381 +    run("test");
    382 +    assert!(path("abc/abc.gcda").exists(), "gcda file not emitted to defined path");
    383 +}
    384 diff --git a/tests/run-make/profile/test.rs b/tests/run-make/profile/test.rs
    385 new file mode 100644
    386 index 00000000000..f328e4d9d04
    387 --- /dev/null
    388 +++ b/tests/run-make/profile/test.rs
    389 @@ -0,0 +1 @@
    390 +fn main() {}