about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs109
-rw-r--r--src/librustc_codegen_ssa/coverageinfo/map.rs6
2 files changed, 62 insertions, 53 deletions
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 236f7f69653..728af7b0a8c 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -90,64 +90,69 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
         args: &Vec<Operand<'tcx>>,
         caller_instance: ty::Instance<'tcx>,
     ) -> bool {
+        let mut is_codegen_intrinsic = true;
+        // Set `is_codegen_intrinsic` to `false` to bypass `codegen_intrinsic_call()`.
+
         if self.tcx.sess.opts.debugging_opts.instrument_coverage {
-            // Add the coverage information from the MIR to the Codegen context. Some coverage
-            // intrinsics are used only to pass along the coverage information (returns `false`
-            // for `is_codegen_intrinsic()`), but `count_code_region` is also converted into an
-            // LLVM intrinsic to increment a coverage counter.
-            match intrinsic {
-                sym::count_code_region => {
-                    use coverage::count_code_region_args::*;
-                    self.add_counter_region(
-                        caller_instance,
-                        op_to_u64(&args[FUNCTION_SOURCE_HASH]),
-                        op_to_u32(&args[COUNTER_ID]),
-                        op_to_u32(&args[START_BYTE_POS]),
-                        op_to_u32(&args[END_BYTE_POS]),
-                    );
-                    return true; // Also inject the counter increment in the backend
-                }
-                sym::coverage_counter_add | sym::coverage_counter_subtract => {
-                    use coverage::coverage_counter_expression_args::*;
-                    self.add_counter_expression_region(
-                        caller_instance,
-                        op_to_u32(&args[EXPRESSION_ID]),
-                        op_to_u32(&args[LEFT_ID]),
-                        if intrinsic == sym::coverage_counter_add {
-                            ExprKind::Add
-                        } else {
-                            ExprKind::Subtract
-                        },
-                        op_to_u32(&args[RIGHT_ID]),
-                        op_to_u32(&args[START_BYTE_POS]),
-                        op_to_u32(&args[END_BYTE_POS]),
-                    );
-                    return false; // Does not inject backend code
+            // If the intrinsic is from the local MIR, add the coverage information to the Codegen
+            // context, to be encoded into the local crate's coverage map.
+            if caller_instance.def_id().is_local() {
+                // FIXME(richkadel): Make sure to add coverage analysis tests on a crate with
+                // external crate dependencies, where:
+                //   1. Both binary and dependent crates are compiled with `-Zinstrument-coverage`
+                //   2. Only binary is compiled with `-Zinstrument-coverage`
+                //   3. Only dependent crates are compiled with `-Zinstrument-coverage`
+                match intrinsic {
+                    sym::count_code_region => {
+                        use coverage::count_code_region_args::*;
+                        self.add_counter_region(
+                            caller_instance,
+                            op_to_u64(&args[FUNCTION_SOURCE_HASH]),
+                            op_to_u32(&args[COUNTER_ID]),
+                            op_to_u32(&args[START_BYTE_POS]),
+                            op_to_u32(&args[END_BYTE_POS]),
+                        );
+                    }
+                    sym::coverage_counter_add | sym::coverage_counter_subtract => {
+                        use coverage::coverage_counter_expression_args::*;
+                        self.add_counter_expression_region(
+                            caller_instance,
+                            op_to_u32(&args[EXPRESSION_ID]),
+                            op_to_u32(&args[LEFT_ID]),
+                            if intrinsic == sym::coverage_counter_add {
+                                ExprKind::Add
+                            } else {
+                                ExprKind::Subtract
+                            },
+                            op_to_u32(&args[RIGHT_ID]),
+                            op_to_u32(&args[START_BYTE_POS]),
+                            op_to_u32(&args[END_BYTE_POS]),
+                        );
+                    }
+                    sym::coverage_unreachable => {
+                        use coverage::coverage_unreachable_args::*;
+                        self.add_unreachable_region(
+                            caller_instance,
+                            op_to_u32(&args[START_BYTE_POS]),
+                            op_to_u32(&args[END_BYTE_POS]),
+                        );
+                    }
+                    _ => {}
                 }
-                sym::coverage_unreachable => {
-                    use coverage::coverage_unreachable_args::*;
-                    self.add_unreachable_region(
-                        caller_instance,
-                        op_to_u32(&args[START_BYTE_POS]),
-                        op_to_u32(&args[END_BYTE_POS]),
-                    );
-                    return false; // Does not inject backend code
+            }
+
+            // Only the `count_code_region` coverage intrinsic is translated into an actual LLVM
+            // intrinsic call (local or not); otherwise, set `is_codegen_intrinsic` to `false`.
+            match intrinsic {
+                sym::coverage_counter_add
+                | sym::coverage_counter_subtract
+                | sym::coverage_unreachable => {
+                    is_codegen_intrinsic = false;
                 }
                 _ => {}
             }
-        } else {
-            // NOT self.tcx.sess.opts.debugging_opts.instrument_coverage
-            if intrinsic == sym::count_code_region {
-                // An external crate may have been pre-compiled with coverage instrumentation, and
-                // some references from the current crate to the external crate might carry along
-                // the call terminators to coverage intrinsics, like `count_code_region` (for
-                // example, when instantiating a generic function). If the current crate has
-                // `instrument_coverage` disabled, the `count_code_region` call terminators should
-                // be ignored.
-                return false; // Do not inject coverage counters inlined from external crates
-            }
         }
-        true // Unhandled intrinsics should be passed to `codegen_intrinsic_call()`
+        is_codegen_intrinsic
     }
 
     fn codegen_intrinsic_call(
diff --git a/src/librustc_codegen_ssa/coverageinfo/map.rs b/src/librustc_codegen_ssa/coverageinfo/map.rs
index 1e36c90baaf..72138065a90 100644
--- a/src/librustc_codegen_ssa/coverageinfo/map.rs
+++ b/src/librustc_codegen_ssa/coverageinfo/map.rs
@@ -86,7 +86,11 @@ impl Region {
     pub fn new(source_map: &SourceMap, start_byte_pos: u32, end_byte_pos: u32) -> Self {
         let start = source_map.lookup_char_pos(BytePos::from_u32(start_byte_pos));
         let end = source_map.lookup_char_pos(BytePos::from_u32(end_byte_pos));
-        assert_eq!(start.file.name, end.file.name);
+        assert_eq!(
+            start.file.name, end.file.name,
+            "Region start ({} -> {:?}) and end ({} -> {:?}) don't come from the same source file!",
+            start_byte_pos, start, end_byte_pos, end
+        );
         Self { start, end }
     }