about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm
diff options
context:
space:
mode:
authorRich Kadel <richkadel@google.com>2021-03-23 14:25:52 -0700
committerRich Kadel <richkadel@google.com>2021-03-23 17:02:10 -0700
commit0859cec65255e34221b3b443f4bdd751549fd4c3 (patch)
tree0b6285ff269bb9e9b1f5315a208c5da42d737cfe /compiler/rustc_codegen_llvm
parent94a3454b0318e506e167f67aa52df1d054c6500b (diff)
downloadrust-0859cec65255e34221b3b443f4bdd751549fd4c3.tar.gz
rust-0859cec65255e34221b3b443f4bdd751549fd4c3.zip
Changes from review comments
Diffstat (limited to 'compiler/rustc_codegen_llvm')
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs26
1 files changed, 23 insertions, 3 deletions
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index 2854717bb6e..32f4fc76b3d 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -73,10 +73,26 @@ impl CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         }
     }
 
+    /// Functions with MIR-based coverage are normally codegenned _only_ if
+    /// called. LLVM coverage tools typically expect every function to be
+    /// defined (even if unused), with at least one call to LLVM intrinsic
+    /// `instrprof.increment`.
+    ///
+    /// Codegen a small function that will never be called, with one counter
+    /// that will never be incremented.
+    ///
+    /// For used/called functions, the coverageinfo was already added to the
+    /// `function_coverage_map` (keyed by function `Instance`) during codegen.
+    /// But in this case, since the unused function was _not_ previously
+    /// codegenned, collect the coverage `CodeRegion`s from the MIR and add
+    /// them. The first `CodeRegion` is used to add a single counter, with the
+    /// same counter ID used in the injected `instrprof.increment` intrinsic
+    /// call. Since the function is never called, all other `CodeRegion`s can be
+    /// added as `unreachable_region`s.
     fn define_unused_fn(&self, def_id: DefId) {
         let instance = declare_unused_fn(self, &def_id);
         codegen_unused_fn_and_counter(self, instance);
-        add_function_coverage(self, instance, def_id);
+        add_unused_function_coverage(self, instance, def_id);
     }
 }
 
@@ -200,7 +216,7 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx
     llvm::set_linkage(llfn, llvm::Linkage::WeakAnyLinkage);
     llvm::set_visibility(llfn, llvm::Visibility::Hidden);
 
-    cx.instances.borrow_mut().insert(instance, llfn);
+    assert!(cx.instances.borrow_mut().insert(instance, llfn).is_none());
 
     instance
 }
@@ -221,7 +237,11 @@ fn codegen_unused_fn_and_counter(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'
     bx.ret_void();
 }
 
-fn add_function_coverage(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>, def_id: DefId) {
+fn add_unused_function_coverage(
+    cx: &CodegenCx<'ll, 'tcx>,
+    instance: Instance<'tcx>,
+    def_id: DefId,
+) {
     let tcx = cx.tcx;
 
     let mut function_coverage = FunctionCoverage::unused(tcx, instance);