From cc832c5de53090a8d25da0f2043177ee8d6048b4 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 11 Aug 2023 11:52:37 +1000 Subject: [PATCH 01/11] =?UTF-8?q?=F0=9F=8D=92=20Add=20tool=20`src/tools/co?= =?UTF-8?q?verage-dump`=20for=20use=20by=20some=20new=20coverage=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 18 ++ Cargo.toml | 1 + src/bootstrap/builder.rs | 3 +- src/bootstrap/tool.rs | 1 + src/tools/coverage-dump/Cargo.toml | 14 + src/tools/coverage-dump/README.md | 8 + src/tools/coverage-dump/src/covfun.rs | 293 ++++++++++++++++++++ src/tools/coverage-dump/src/main.rs | 17 ++ src/tools/coverage-dump/src/parser.rs | 80 ++++++ src/tools/coverage-dump/src/parser/tests.rs | 38 +++ src/tools/coverage-dump/src/prf_names.rs | 85 ++++++ 11 files changed, 557 insertions(+), 1 deletion(-) create mode 100644 src/tools/coverage-dump/Cargo.toml create mode 100644 src/tools/coverage-dump/README.md create mode 100644 src/tools/coverage-dump/src/covfun.rs create mode 100644 src/tools/coverage-dump/src/main.rs create mode 100644 src/tools/coverage-dump/src/parser.rs create mode 100644 src/tools/coverage-dump/src/parser/tests.rs create mode 100644 src/tools/coverage-dump/src/prf_names.rs diff --git a/Cargo.lock b/Cargo.lock index 4ebbb16442eaa..510a0150b5ae9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -703,6 +703,18 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +[[package]] +name = "coverage-dump" +version = "0.1.0" +dependencies = [ + "anyhow", + "leb128", + "md-5", + "miniz_oxide", + "regex", + "rustc-demangle", +] + [[package]] name = "coverage_test_macros" version = "0.0.0" @@ -2009,6 +2021,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + [[package]] name = "libc" version = "0.2.147" diff --git a/Cargo.toml b/Cargo.toml index d2e84d5426f9f..9b11ae8744b4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ members = [ "src/tools/generate-windows-sys", "src/tools/rustdoc-gui-test", "src/tools/opt-dist", + "src/tools/coverage-dump", ] exclude = [ diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index b366619285338..73c0a192cef94 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -703,7 +703,8 @@ impl<'a> Builder<'a> { llvm::Lld, llvm::CrtBeginEnd, tool::RustdocGUITest, - tool::OptimizedDist + tool::OptimizedDist, + tool::CoverageDump, ), Kind::Check | Kind::Clippy | Kind::Fix => describe!( check::Std, diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 07ff3da6b4aa5..f094dd9d7c90b 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -306,6 +306,7 @@ bootstrap_tool!( GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys"; RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = "test"; OptimizedDist, "src/tools/opt-dist", "opt-dist"; + CoverageDump, "src/tools/coverage-dump", "coverage-dump"; ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] diff --git a/src/tools/coverage-dump/Cargo.toml b/src/tools/coverage-dump/Cargo.toml new file mode 100644 index 0000000000000..7f14286b5d0c4 --- /dev/null +++ b/src/tools/coverage-dump/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "coverage-dump" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.71" +leb128 = "0.2.5" +md5 = { package = "md-5" , version = "0.10.5" } +miniz_oxide = "0.7.1" +regex = "1.8.4" +rustc-demangle = "0.1.23" diff --git a/src/tools/coverage-dump/README.md b/src/tools/coverage-dump/README.md new file mode 100644 index 0000000000000..e2625d5adf27e --- /dev/null +++ b/src/tools/coverage-dump/README.md @@ -0,0 +1,8 @@ +This tool extracts coverage mapping information from an LLVM IR assembly file +(`.ll`), and prints it in a more human-readable form that can be used for +snapshot tests. + +The output format is mostly arbitrary, so it's OK to change the output as long +as any affected tests are also re-blessed. However, the output should be +consistent across different executions on different platforms, so avoid +printing any information that is platform-specific or non-deterministic. diff --git a/src/tools/coverage-dump/src/covfun.rs b/src/tools/coverage-dump/src/covfun.rs new file mode 100644 index 0000000000000..d07ba3e82f051 --- /dev/null +++ b/src/tools/coverage-dump/src/covfun.rs @@ -0,0 +1,293 @@ +use crate::parser::{unescape_llvm_string_contents, Parser}; +use anyhow::{anyhow, Context}; +use regex::Regex; +use std::collections::HashMap; +use std::fmt::{self, Debug, Write as _}; +use std::sync::OnceLock; + +pub(crate) fn dump_covfun_mappings( + llvm_ir: &str, + function_names: &HashMap, +) -> anyhow::Result<()> { + // Extract function coverage entries from the LLVM IR assembly, and associate + // each entry with its (demangled) name. + let mut covfun_entries = llvm_ir + .lines() + .filter_map(covfun_line_data) + .map(|line_data| (function_names.get(&line_data.name_hash).map(String::as_str), line_data)) + .collect::>(); + covfun_entries.sort_by(|a, b| { + // Sort entries primarily by name, to help make the order consistent + // across platforms and relatively insensitive to changes. + // (Sadly we can't use `sort_by_key` because we would need to return references.) + Ord::cmp(&a.0, &b.0) + .then_with(|| Ord::cmp(&a.1.is_used, &b.1.is_used)) + .then_with(|| Ord::cmp(a.1.payload.as_slice(), b.1.payload.as_slice())) + }); + + for (name, line_data) in &covfun_entries { + let name = name.unwrap_or("(unknown)"); + let unused = if line_data.is_used { "" } else { " (unused)" }; + println!("Function name: {name}{unused}"); + + let payload: &[u8] = &line_data.payload; + println!("Raw bytes ({len}): 0x{payload:02x?}", len = payload.len()); + + let mut parser = Parser::new(payload); + + let num_files = parser.read_uleb128_u32()?; + println!("Number of files: {num_files}"); + + for i in 0..num_files { + let global_file_id = parser.read_uleb128_u32()?; + println!("- file {i} => global file {global_file_id}"); + } + + let num_expressions = parser.read_uleb128_u32()?; + println!("Number of expressions: {num_expressions}"); + + let mut expression_resolver = ExpressionResolver::new(); + for i in 0..num_expressions { + let lhs = parser.read_simple_operand()?; + let rhs = parser.read_simple_operand()?; + println!("- expression {i} operands: lhs = {lhs:?}, rhs = {rhs:?}"); + expression_resolver.push_operands(lhs, rhs); + } + + for i in 0..num_files { + let num_mappings = parser.read_uleb128_u32()?; + println!("Number of file {i} mappings: {num_mappings}"); + + for _ in 0..num_mappings { + let (kind, region) = parser.read_mapping_kind_and_region()?; + println!("- {kind:?} at {region:?}"); + + match kind { + // Also print expression mappings in resolved form. + MappingKind::Code(operand @ Operand::Expression { .. }) + | MappingKind::Gap(operand @ Operand::Expression { .. }) => { + println!(" = {}", expression_resolver.format_operand(operand)); + } + // If the mapping is a branch region, print both of its arms + // in resolved form (even if they aren't expressions). + MappingKind::Branch { r#true, r#false } => { + println!(" true = {}", expression_resolver.format_operand(r#true)); + println!(" false = {}", expression_resolver.format_operand(r#false)); + } + _ => (), + } + } + } + + parser.ensure_empty()?; + println!(); + } + Ok(()) +} + +struct CovfunLineData { + name_hash: u64, + is_used: bool, + payload: Vec, +} + +/// Checks a line of LLVM IR assembly to see if it contains an `__llvm_covfun` +/// entry, and if so extracts relevant data in a `CovfunLineData`. +fn covfun_line_data(line: &str) -> Option { + let re = { + // We cheat a little bit and match variable names `@__covrec_[HASH]u` + // rather than the section name, because the section name is harder to + // extract and differs across Linux/Windows/macOS. We also extract the + // symbol name hash from the variable name rather than the data, since + // it's easier and both should match. + static RE: OnceLock = OnceLock::new(); + RE.get_or_init(|| { + Regex::new( + r#"^@__covrec_(?[0-9A-Z]+)(?u)? = .*\[[0-9]+ x i8\] c"(?[^"]*)".*$"#, + ) + .unwrap() + }) + }; + + let captures = re.captures(line)?; + let name_hash = u64::from_str_radix(&captures["name_hash"], 16).unwrap(); + let is_used = captures.name("is_used").is_some(); + let payload = unescape_llvm_string_contents(&captures["payload"]); + + Some(CovfunLineData { name_hash, is_used, payload }) +} + +// Extra parser methods only needed when parsing `covfun` payloads. +impl<'a> Parser<'a> { + fn read_simple_operand(&mut self) -> anyhow::Result { + let raw_operand = self.read_uleb128_u32()?; + Operand::decode(raw_operand).context("decoding operand") + } + + fn read_mapping_kind_and_region(&mut self) -> anyhow::Result<(MappingKind, MappingRegion)> { + let mut kind = self.read_raw_mapping_kind()?; + let mut region = self.read_raw_mapping_region()?; + + const HIGH_BIT: u32 = 1u32 << 31; + if region.end_column & HIGH_BIT != 0 { + region.end_column &= !HIGH_BIT; + kind = match kind { + MappingKind::Code(operand) => MappingKind::Gap(operand), + // LLVM's coverage mapping reader will actually handle this + // case without complaint, but the result is almost certainly + // a meaningless implementation artifact. + _ => return Err(anyhow!("unexpected base kind for gap region: {kind:?}")), + } + } + + Ok((kind, region)) + } + + fn read_raw_mapping_kind(&mut self) -> anyhow::Result { + let raw_mapping_kind = self.read_uleb128_u32()?; + if let Some(operand) = Operand::decode(raw_mapping_kind) { + return Ok(MappingKind::Code(operand)); + } + + assert_eq!(raw_mapping_kind & 0b11, 0); + assert_ne!(raw_mapping_kind, 0); + + let (high, is_expansion) = (raw_mapping_kind >> 3, raw_mapping_kind & 0b100 != 0); + if is_expansion { + Ok(MappingKind::Expansion(high)) + } else { + match high { + 0 => unreachable!("zero kind should have already been handled as a code mapping"), + 2 => Ok(MappingKind::Skip), + 4 => { + let r#true = self.read_simple_operand()?; + let r#false = self.read_simple_operand()?; + Ok(MappingKind::Branch { r#true, r#false }) + } + _ => Err(anyhow!("unknown mapping kind: {raw_mapping_kind:#x}")), + } + } + } + + fn read_raw_mapping_region(&mut self) -> anyhow::Result { + let start_line_offset = self.read_uleb128_u32()?; + let start_column = self.read_uleb128_u32()?; + let end_line_offset = self.read_uleb128_u32()?; + let end_column = self.read_uleb128_u32()?; + Ok(MappingRegion { start_line_offset, start_column, end_line_offset, end_column }) + } +} + +// Represents an expression operand (lhs/rhs), branch region operand (true/false), +// or the value used by a code region or gap region. +#[derive(Clone, Copy, Debug)] +pub(crate) enum Operand { + Zero, + Counter(u32), + Expression(u32, Op), +} + +/// Operator (addition or subtraction) used by an expression. +#[derive(Clone, Copy, Debug)] +pub(crate) enum Op { + Sub, + Add, +} + +impl Operand { + pub(crate) fn decode(input: u32) -> Option { + let (high, tag) = (input >> 2, input & 0b11); + match tag { + 0b00 if high == 0 => Some(Self::Zero), + 0b01 => Some(Self::Counter(high)), + 0b10 => Some(Self::Expression(high, Op::Sub)), + 0b11 => Some(Self::Expression(high, Op::Add)), + // When reading expression or branch operands, the LLVM coverage + // mapping reader will always interpret a `0b00` tag as a zero + // operand, even when the high bits are non-zero. + // We treat that case as failure instead, so that this code can be + // shared by the full mapping-kind reader as well. + _ => None, + } + } +} + +#[derive(Debug)] +enum MappingKind { + Code(Operand), + Gap(Operand), + Expansion(u32), + Skip, + // Using raw identifiers here makes the dump output a little bit nicer + // (via the derived Debug), at the expense of making this tool's source + // code a little bit uglier. + Branch { r#true: Operand, r#false: Operand }, +} + +struct MappingRegion { + /// Offset of this region's start line, relative to the *start line* of + /// the *previous mapping* (or 0). Line numbers are 1-based. + start_line_offset: u32, + /// This region's start column, absolute and 1-based. + start_column: u32, + /// Offset of this region's end line, relative to the *this mapping's* + /// start line. Line numbers are 1-based. + end_line_offset: u32, + /// This region's end column, absolute, 1-based, and exclusive. + /// + /// If the highest bit is set, that bit is cleared and the associated + /// mapping becomes a gap region mapping. + end_column: u32, +} + +impl Debug for MappingRegion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "(prev + {}, {}) to (start + {}, {})", + self.start_line_offset, self.start_column, self.end_line_offset, self.end_column + ) + } +} + +/// Helper type that prints expressions in a "resolved" form, so that +/// developers reading the dump don't need to resolve expressions by hand. +struct ExpressionResolver { + operands: Vec<(Operand, Operand)>, +} + +impl ExpressionResolver { + fn new() -> Self { + Self { operands: Vec::new() } + } + + fn push_operands(&mut self, lhs: Operand, rhs: Operand) { + self.operands.push((lhs, rhs)); + } + + fn format_operand(&self, operand: Operand) -> String { + let mut output = String::new(); + self.write_operand(&mut output, operand); + output + } + + fn write_operand(&self, output: &mut String, operand: Operand) { + match operand { + Operand::Zero => output.push_str("Zero"), + Operand::Counter(id) => write!(output, "c{id}").unwrap(), + Operand::Expression(id, op) => { + let (lhs, rhs) = self.operands[id as usize]; + let op = match op { + Op::Sub => "-", + Op::Add => "+", + }; + + output.push('('); + self.write_operand(output, lhs); + write!(output, " {op} ").unwrap(); + self.write_operand(output, rhs); + output.push(')'); + } + } + } +} diff --git a/src/tools/coverage-dump/src/main.rs b/src/tools/coverage-dump/src/main.rs new file mode 100644 index 0000000000000..93fed1799e041 --- /dev/null +++ b/src/tools/coverage-dump/src/main.rs @@ -0,0 +1,17 @@ +mod covfun; +mod parser; +mod prf_names; + +fn main() -> anyhow::Result<()> { + use anyhow::Context as _; + + let args = std::env::args().collect::>(); + + let llvm_ir_path = args.get(1).context("LLVM IR file not specified")?; + let llvm_ir = std::fs::read_to_string(llvm_ir_path).context("couldn't read LLVM IR file")?; + + let function_names = crate::prf_names::make_function_names_table(&llvm_ir)?; + crate::covfun::dump_covfun_mappings(&llvm_ir, &function_names)?; + + Ok(()) +} diff --git a/src/tools/coverage-dump/src/parser.rs b/src/tools/coverage-dump/src/parser.rs new file mode 100644 index 0000000000000..eefac1a4f94c1 --- /dev/null +++ b/src/tools/coverage-dump/src/parser.rs @@ -0,0 +1,80 @@ +#[cfg(test)] +mod tests; + +use anyhow::ensure; +use regex::bytes; +use std::sync::OnceLock; + +/// Given the raw contents of a string literal in LLVM IR assembly, decodes any +/// backslash escapes and returns a vector containing the resulting byte string. +pub(crate) fn unescape_llvm_string_contents(contents: &str) -> Vec { + let escape_re = { + static RE: OnceLock = OnceLock::new(); + // LLVM IR supports two string escapes: `\\` and `\xx`. + RE.get_or_init(|| bytes::Regex::new(r"\\\\|\\([0-9A-Za-z]{2})").unwrap()) + }; + + fn u8_from_hex_digits(digits: &[u8]) -> u8 { + // We know that the input contains exactly 2 hex digits, so these calls + // should never fail. + assert_eq!(digits.len(), 2); + let digits = std::str::from_utf8(digits).unwrap(); + u8::from_str_radix(digits, 16).unwrap() + } + + escape_re + .replace_all(contents.as_bytes(), |captures: &bytes::Captures<'_>| { + let byte = match captures.get(1) { + None => b'\\', + Some(hex_digits) => u8_from_hex_digits(hex_digits.as_bytes()), + }; + [byte] + }) + .into_owned() +} + +pub(crate) struct Parser<'a> { + rest: &'a [u8], +} + +impl<'a> Parser<'a> { + pub(crate) fn new(input: &'a [u8]) -> Self { + Self { rest: input } + } + + pub(crate) fn ensure_empty(self) -> anyhow::Result<()> { + ensure!(self.rest.is_empty(), "unparsed bytes: 0x{:02x?}", self.rest); + Ok(()) + } + + pub(crate) fn read_n_bytes(&mut self, n: usize) -> anyhow::Result<&'a [u8]> { + ensure!(n <= self.rest.len()); + + let (bytes, rest) = self.rest.split_at(n); + self.rest = rest; + Ok(bytes) + } + + pub(crate) fn read_uleb128_u32(&mut self) -> anyhow::Result { + self.read_uleb128_u64_and_convert() + } + + pub(crate) fn read_uleb128_usize(&mut self) -> anyhow::Result { + self.read_uleb128_u64_and_convert() + } + + fn read_uleb128_u64_and_convert(&mut self) -> anyhow::Result + where + T: TryFrom + 'static, + T::Error: std::error::Error + Send + Sync, + { + let mut temp_rest = self.rest; + let raw_value: u64 = leb128::read::unsigned(&mut temp_rest)?; + let converted_value = T::try_from(raw_value)?; + + // Only update `self.rest` if the above steps succeeded, so that the + // parser position can be used for error reporting if desired. + self.rest = temp_rest; + Ok(converted_value) + } +} diff --git a/src/tools/coverage-dump/src/parser/tests.rs b/src/tools/coverage-dump/src/parser/tests.rs new file mode 100644 index 0000000000000..a673606b9c4c8 --- /dev/null +++ b/src/tools/coverage-dump/src/parser/tests.rs @@ -0,0 +1,38 @@ +use super::unescape_llvm_string_contents; + +// WARNING: These tests don't necessarily run in CI, and were mainly used to +// help track down problems when originally developing this tool. +// (The tool is still tested indirectly by snapshot tests that rely on it.) + +// Tests for `unescape_llvm_string_contents`: + +#[test] +fn unescape_empty() { + assert_eq!(unescape_llvm_string_contents(""), &[]); +} + +#[test] +fn unescape_noop() { + let input = "The quick brown fox jumps over the lazy dog."; + assert_eq!(unescape_llvm_string_contents(input), input.as_bytes()); +} + +#[test] +fn unescape_backslash() { + let input = r"\\Hello\\world\\"; + assert_eq!(unescape_llvm_string_contents(input), r"\Hello\world\".as_bytes()); +} + +#[test] +fn unescape_hex() { + let input = r"\01\02\03\04\0a\0b\0C\0D\fd\fE\FF"; + let expected: &[u8] = &[0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d, 0xfd, 0xfe, 0xff]; + assert_eq!(unescape_llvm_string_contents(input), expected); +} + +#[test] +fn unescape_mixed() { + let input = r"\\01.\5c\5c"; + let expected: &[u8] = br"\01.\\"; + assert_eq!(unescape_llvm_string_contents(input), expected); +} diff --git a/src/tools/coverage-dump/src/prf_names.rs b/src/tools/coverage-dump/src/prf_names.rs new file mode 100644 index 0000000000000..2c0c942e630ce --- /dev/null +++ b/src/tools/coverage-dump/src/prf_names.rs @@ -0,0 +1,85 @@ +use crate::parser::{unescape_llvm_string_contents, Parser}; +use anyhow::{anyhow, ensure}; +use regex::Regex; +use std::collections::HashMap; +use std::sync::OnceLock; + +/// Scans through the contents of an LLVM IR assembly file to find `__llvm_prf_names` +/// entries, decodes them, and creates a table that maps name hash values to +/// (demangled) function names. +pub(crate) fn make_function_names_table(llvm_ir: &str) -> anyhow::Result> { + fn prf_names_payload(line: &str) -> Option<&str> { + let re = { + // We cheat a little bit and match the variable name `@__llvm_prf_nm` + // rather than the section name, because the section name is harder + // to extract and differs across Linux/Windows/macOS. + static RE: OnceLock = OnceLock::new(); + RE.get_or_init(|| { + Regex::new(r#"^@__llvm_prf_nm =.*\[[0-9]+ x i8\] c"([^"]*)".*$"#).unwrap() + }) + }; + + let payload = re.captures(line)?.get(1).unwrap().as_str(); + Some(payload) + } + + /// LLVM's profiler/coverage metadata often uses an MD5 hash truncated to + /// 64 bits as a way to associate data stored in different tables/sections. + fn truncated_md5(bytes: &[u8]) -> u64 { + use md5::{Digest, Md5}; + let mut hasher = Md5::new(); + hasher.update(bytes); + let hash: [u8; 8] = hasher.finalize().as_slice()[..8].try_into().unwrap(); + u64::from_le_bytes(hash) + } + + fn demangle_if_able(symbol_name_bytes: &[u8]) -> anyhow::Result { + // In practice, raw symbol names should always be ASCII. + let symbol_name_str = std::str::from_utf8(symbol_name_bytes)?; + match rustc_demangle::try_demangle(symbol_name_str) { + Ok(d) => Ok(format!("{d:#}")), + // If demangling failed, don't treat it as an error. This lets us + // run the dump tool against non-Rust coverage maps produced by + // `clang`, for testing purposes. + Err(_) => Ok(format!("(couldn't demangle) {symbol_name_str}")), + } + } + + let mut map = HashMap::new(); + + for payload in llvm_ir.lines().filter_map(prf_names_payload).map(unescape_llvm_string_contents) + { + let mut parser = Parser::new(&payload); + let uncompressed_len = parser.read_uleb128_usize()?; + let compressed_len = parser.read_uleb128_usize()?; + + let uncompressed_bytes_vec; + let uncompressed_bytes: &[u8] = if compressed_len == 0 { + // The symbol name bytes are uncompressed, so read them directly. + parser.read_n_bytes(uncompressed_len)? + } else { + // The symbol name bytes are compressed, so read and decompress them. + let compressed_bytes = parser.read_n_bytes(compressed_len)?; + + uncompressed_bytes_vec = miniz_oxide::inflate::decompress_to_vec_zlib_with_limit( + compressed_bytes, + uncompressed_len, + ) + .map_err(|e| anyhow!("{e:?}"))?; + ensure!(uncompressed_bytes_vec.len() == uncompressed_len); + + &uncompressed_bytes_vec + }; + + // Symbol names in the payload are separated by `0x01` bytes. + for raw_name in uncompressed_bytes.split(|&b| b == 0x01) { + let hash = truncated_md5(raw_name); + let demangled = demangle_if_able(raw_name)?; + map.insert(hash, demangled); + } + + parser.ensure_empty()?; + } + + Ok(map) +} From d348d9fe1a52e714540fdfa923d4ad8199c2895f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 14 Aug 2023 13:00:28 +1000 Subject: [PATCH 02/11] =?UTF-8?q?=F0=9F=8D=92=20Add=20test=20suite=20`cove?= =?UTF-8?q?rage-map`=20to=20test=20coverage=20mappings=20emitted=20by=20LL?= =?UTF-8?q?VM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We compile each test file to LLVM IR assembly, and then pass that IR to a dedicated program that can decode LLVM coverage maps and print them in a more human-readable format. We can then check that output against known-good snapshots. This test suite has some advantages over the existing `run-coverage` tests: - We can test coverage instrumentation without needing to run target binaries. - We can observe subtle improvements/regressions in the underlying coverage mappings that don't make a visible difference to coverage reports. --- src/bootstrap/builder.rs | 1 + src/bootstrap/test.rs | 14 +++ src/tools/compiletest/src/common.rs | 6 + src/tools/compiletest/src/lib.rs | 2 + src/tools/compiletest/src/runtest.rs | 55 ++++++++- tests/coverage-map/if.cov-map | 15 +++ tests/coverage-map/if.rs | 9 ++ tests/coverage-map/long_and_wide.cov-map | 32 +++++ tests/coverage-map/long_and_wide.rs | 150 +++++++++++++++++++++++ tests/coverage-map/trivial.cov-map | 8 ++ tests/coverage-map/trivial.rs | 3 + 11 files changed, 293 insertions(+), 2 deletions(-) create mode 100644 tests/coverage-map/if.cov-map create mode 100644 tests/coverage-map/if.rs create mode 100644 tests/coverage-map/long_and_wide.cov-map create mode 100644 tests/coverage-map/long_and_wide.rs create mode 100644 tests/coverage-map/trivial.cov-map create mode 100644 tests/coverage-map/trivial.rs diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 73c0a192cef94..a24a6a4636d48 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -726,6 +726,7 @@ impl<'a> Builder<'a> { test::Tidy, test::Ui, test::RunPassValgrind, + test::CoverageMap, test::RunCoverage, test::MirOpt, test::Codegen, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index db3b7ffbea4e5..4e944334485fb 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1335,6 +1335,12 @@ host_test!(RunMakeFullDeps { default_test!(Assembly { path: "tests/assembly", mode: "assembly", suite: "assembly" }); +default_test!(CoverageMap { + path: "tests/coverage-map", + mode: "coverage-map", + suite: "coverage-map" +}); + host_test!(RunCoverage { path: "tests/run-coverage", mode: "run-coverage", suite: "run-coverage" }); host_test!(RunCoverageRustdoc { path: "tests/run-coverage-rustdoc", @@ -1540,6 +1546,14 @@ note: if you're sure you want to do this, please open an issue as to why. In the .arg(builder.ensure(tool::JsonDocLint { compiler: json_compiler, target })); } + if mode == "coverage-map" { + let coverage_dump = builder.ensure(tool::CoverageDump { + compiler: compiler.with_stage(0), + target: compiler.host, + }); + cmd.arg("--coverage-dump-path").arg(coverage_dump); + } + if mode == "run-make" || mode == "run-coverage" { let rust_demangler = builder .ensure(tool::RustDemangler { diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 7c17e92d0dfe2..b91d5a958bb62 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -66,6 +66,7 @@ string_enum! { JsDocTest => "js-doc-test", MirOpt => "mir-opt", Assembly => "assembly", + CoverageMap => "coverage-map", RunCoverage => "run-coverage", } } @@ -161,6 +162,9 @@ pub struct Config { /// The rust-demangler executable. pub rust_demangler_path: Option, + /// The coverage-dump executable. + pub coverage_dump_path: Option, + /// The Python executable to use for LLDB and htmldocck. pub python: String, @@ -639,6 +643,7 @@ pub const UI_EXTENSIONS: &[&str] = &[ UI_STDERR_32, UI_STDERR_16, UI_COVERAGE, + UI_COVERAGE_MAP, ]; pub const UI_STDERR: &str = "stderr"; pub const UI_STDOUT: &str = "stdout"; @@ -649,6 +654,7 @@ pub const UI_STDERR_64: &str = "64bit.stderr"; pub const UI_STDERR_32: &str = "32bit.stderr"; pub const UI_STDERR_16: &str = "16bit.stderr"; pub const UI_COVERAGE: &str = "coverage"; +pub const UI_COVERAGE_MAP: &str = "cov-map"; /// Absolute path to the directory where all output for all tests in the given /// `relative_dir` group should reside. Example: diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 1a765477fe501..619ff9b322114 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -48,6 +48,7 @@ pub fn parse_config(args: Vec) -> Config { .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH") .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH") .optopt("", "rust-demangler-path", "path to rust-demangler to use in tests", "PATH") + .optopt("", "coverage-dump-path", "path to coverage-dump to use in tests", "PATH") .reqopt("", "python", "path to python to use for doc tests", "PATH") .optopt("", "jsondocck-path", "path to jsondocck to use for doc tests", "PATH") .optopt("", "jsondoclint-path", "path to jsondoclint to use for doc tests", "PATH") @@ -218,6 +219,7 @@ pub fn parse_config(args: Vec) -> Config { rustc_path: opt_path(matches, "rustc-path"), rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from), rust_demangler_path: matches.opt_str("rust-demangler-path").map(PathBuf::from), + coverage_dump_path: matches.opt_str("coverage-dump-path").map(PathBuf::from), python: matches.opt_str("python").unwrap(), jsondocck_path: matches.opt_str("jsondocck-path"), jsondoclint_path: matches.opt_str("jsondoclint-path"), diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 4ef79af3124a8..dcdba1fa8bb4b 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -6,8 +6,8 @@ use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, RustdocJs use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc}; use crate::common::{CompareMode, FailMode, PassMode}; use crate::common::{Config, TestPaths}; -use crate::common::{Pretty, RunCoverage, RunPassValgrind}; -use crate::common::{UI_COVERAGE, UI_RUN_STDERR, UI_RUN_STDOUT}; +use crate::common::{CoverageMap, Pretty, RunCoverage, RunPassValgrind}; +use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP, UI_RUN_STDERR, UI_RUN_STDOUT}; use crate::compute_diff::{write_diff, write_filtered_diff}; use crate::errors::{self, Error, ErrorKind}; use crate::header::TestProps; @@ -254,6 +254,7 @@ impl<'test> TestCx<'test> { MirOpt => self.run_mir_opt_test(), Assembly => self.run_assembly_test(), JsDocTest => self.run_js_doc_test(), + CoverageMap => self.run_coverage_map_test(), RunCoverage => self.run_coverage_test(), } } @@ -467,6 +468,46 @@ impl<'test> TestCx<'test> { } } + fn run_coverage_map_test(&self) { + let Some(coverage_dump_path) = &self.config.coverage_dump_path else { + self.fatal("missing --coverage-dump"); + }; + + let proc_res = self.compile_test_and_save_ir(); + if !proc_res.status.success() { + self.fatal_proc_rec("compilation failed!", &proc_res); + } + drop(proc_res); + + let llvm_ir_path = self.output_base_name().with_extension("ll"); + + let mut dump_command = Command::new(coverage_dump_path); + dump_command.arg(llvm_ir_path); + let proc_res = self.run_command_to_procres(&mut dump_command); + if !proc_res.status.success() { + self.fatal_proc_rec("coverage-dump failed!", &proc_res); + } + + let kind = UI_COVERAGE_MAP; + + let expected_coverage_dump = self.load_expected_output(kind); + let actual_coverage_dump = self.normalize_output(&proc_res.stdout, &[]); + + let coverage_dump_errors = self.compare_output( + kind, + &actual_coverage_dump, + &expected_coverage_dump, + self.props.compare_output_lines_by_subset, + ); + + if coverage_dump_errors > 0 { + self.fatal_proc_rec( + &format!("{coverage_dump_errors} errors occurred comparing coverage output."), + &proc_res, + ); + } + } + fn run_coverage_test(&self) { let should_run = self.run_if_enabled(); let proc_res = self.compile_test(should_run, Emit::None); @@ -650,6 +691,10 @@ impl<'test> TestCx<'test> { let mut cmd = Command::new(tool_path); configure_cmd_fn(&mut cmd); + self.run_command_to_procres(&mut cmd) + } + + fn run_command_to_procres(&self, cmd: &mut Command) -> ProcRes { let output = cmd.output().unwrap_or_else(|_| panic!("failed to exec `{cmd:?}`")); let proc_res = ProcRes { @@ -2399,6 +2444,12 @@ impl<'test> TestCx<'test> { rustc.arg(dir_opt); } + CoverageMap => { + rustc.arg("-Cinstrument-coverage"); + // These tests only compile to MIR, so they don't need the + // profiler runtime to be present. + rustc.arg("-Zno-profiler-runtime"); + } RunCoverage => { rustc.arg("-Cinstrument-coverage"); } diff --git a/tests/coverage-map/if.cov-map b/tests/coverage-map/if.cov-map new file mode 100644 index 0000000000000..3cedb5ffbecb1 --- /dev/null +++ b/tests/coverage-map/if.cov-map @@ -0,0 +1,15 @@ +Function name: if::main +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 3, 1) to (start + 2, 12) +- Code(Counter(1)) at (prev + 2, 13) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 5) to (start + 1, 2) + = (c1 + (c0 - c1)) + diff --git a/tests/coverage-map/if.rs b/tests/coverage-map/if.rs new file mode 100644 index 0000000000000..ed3f69bdc98d2 --- /dev/null +++ b/tests/coverage-map/if.rs @@ -0,0 +1,9 @@ +// compile-flags: --edition=2021 + +fn main() { + let cond = std::env::args().len() == 1; + if cond { + println!("true"); + } + println!("done"); +} diff --git a/tests/coverage-map/long_and_wide.cov-map b/tests/coverage-map/long_and_wide.cov-map new file mode 100644 index 0000000000000..97aebf9b18ab0 --- /dev/null +++ b/tests/coverage-map/long_and_wide.cov-map @@ -0,0 +1,32 @@ +Function name: long_and_wide::far_function +Raw bytes (10): 0x[01, 01, 00, 01, 01, 96, 01, 01, 00, 15] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 150, 1) to (start + 0, 21) + +Function name: long_and_wide::long_function +Raw bytes (10): 0x[01, 01, 00, 01, 01, 10, 01, 84, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 16, 1) to (start + 132, 2) + +Function name: long_and_wide::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 04, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 7, 1) to (start + 4, 2) + +Function name: long_and_wide::wide_function +Raw bytes (10): 0x[01, 01, 00, 01, 01, 0e, 01, 00, 8b, 01] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 14, 1) to (start + 0, 139) + diff --git a/tests/coverage-map/long_and_wide.rs b/tests/coverage-map/long_and_wide.rs new file mode 100644 index 0000000000000..a7cbcd4802791 --- /dev/null +++ b/tests/coverage-map/long_and_wide.rs @@ -0,0 +1,150 @@ +// compile-flags: --edition=2021 +// ignore-tidy-linelength + +// This file deliberately contains line and column numbers larger than 127, +// to verify that `coverage-dump`'s ULEB128 parser can handle them. + +fn main() { + wide_function(); + long_function(); + far_function(); +} + +#[rustfmt::skip] +fn wide_function() { /* */ (); } + +fn long_function() { + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // +} + +fn far_function() {} diff --git a/tests/coverage-map/trivial.cov-map b/tests/coverage-map/trivial.cov-map new file mode 100644 index 0000000000000..874e294a1c498 --- /dev/null +++ b/tests/coverage-map/trivial.cov-map @@ -0,0 +1,8 @@ +Function name: trivial::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 01, 00, 0d] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 13) + diff --git a/tests/coverage-map/trivial.rs b/tests/coverage-map/trivial.rs new file mode 100644 index 0000000000000..d0a9b44fb3605 --- /dev/null +++ b/tests/coverage-map/trivial.rs @@ -0,0 +1,3 @@ +// compile-flags: --edition=2021 + +fn main() {} From 05b398ee005b22acb1047bddf13ca4b9ba827db8 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 14 Aug 2023 21:29:41 +1000 Subject: [PATCH 03/11] =?UTF-8?q?=F0=9F=8D=92=20Copy=20a=20selection=20of?= =?UTF-8?q?=20`run-coverage`=20test=20files=20into=20`coverage-map`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The output of these tests is too complicated to comfortably verify by hand, but we can still use them to observe changes to the underlying mappings produced by codegen/LLVM. --- tests/coverage-map/status-quo/README.md | 9 + tests/coverage-map/status-quo/async2.cov-map | 136 ++++++++++++ tests/coverage-map/status-quo/async2.rs | 69 +++++++ .../status-quo/conditions.cov-map | 186 +++++++++++++++++ tests/coverage-map/status-quo/conditions.rs | 87 ++++++++ .../status-quo/drop_trait.cov-map | 21 ++ tests/coverage-map/status-quo/drop_trait.rs | 33 +++ .../coverage-map/status-quo/generics.cov-map | 45 ++++ tests/coverage-map/status-quo/generics.rs | 48 +++++ .../status-quo/loops_branches.cov-map | 193 ++++++++++++++++++ .../coverage-map/status-quo/loops_branches.rs | 61 ++++++ tests/coverage-map/status-quo/unused.cov-map | 94 +++++++++ tests/coverage-map/status-quo/unused.rs | 39 ++++ 13 files changed, 1021 insertions(+) create mode 100644 tests/coverage-map/status-quo/README.md create mode 100644 tests/coverage-map/status-quo/async2.cov-map create mode 100644 tests/coverage-map/status-quo/async2.rs create mode 100644 tests/coverage-map/status-quo/conditions.cov-map create mode 100644 tests/coverage-map/status-quo/conditions.rs create mode 100644 tests/coverage-map/status-quo/drop_trait.cov-map create mode 100644 tests/coverage-map/status-quo/drop_trait.rs create mode 100644 tests/coverage-map/status-quo/generics.cov-map create mode 100644 tests/coverage-map/status-quo/generics.rs create mode 100644 tests/coverage-map/status-quo/loops_branches.cov-map create mode 100644 tests/coverage-map/status-quo/loops_branches.rs create mode 100644 tests/coverage-map/status-quo/unused.cov-map create mode 100644 tests/coverage-map/status-quo/unused.rs diff --git a/tests/coverage-map/status-quo/README.md b/tests/coverage-map/status-quo/README.md new file mode 100644 index 0000000000000..c3b9f16ac54ff --- /dev/null +++ b/tests/coverage-map/status-quo/README.md @@ -0,0 +1,9 @@ +The tests in this directory were copied from `tests/run-coverage` in order to +capture the current behavior of the instrumentor on non-trivial programs. +The actual mappings have not been closely inspected. + +## Maintenance note + +If a MIR optimization or LLVM upgrade causes these tests to fail, +it should usually be OK to just `--bless` them, +as long as the `run-coverage` test suite still works. diff --git a/tests/coverage-map/status-quo/async2.cov-map b/tests/coverage-map/status-quo/async2.cov-map new file mode 100644 index 0000000000000..e02db200ba029 --- /dev/null +++ b/tests/coverage-map/status-quo/async2.cov-map @@ -0,0 +1,136 @@ +Function name: async2::async_func +Raw bytes (9): 0x[01, 01, 00, 01, 01, 14, 01, 00, 17] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 20, 1) to (start + 0, 23) + +Function name: async2::async_func::{closure#0} +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 14, 17, 03, 09, 05, 03, 0a, 02, 06, 02, 02, 06, 00, 07, 07, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 20, 23) to (start + 3, 9) +- Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + +Function name: async2::async_func_just_println +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 01, 00, 24] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 31, 1) to (start + 0, 36) + +Function name: async2::async_func_just_println::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 24, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 31, 36) to (start + 2, 2) + +Function name: async2::executor::block_on:: +Raw bytes (44): 0x[01, 01, 05, 0b, 05, 01, 05, 01, 05, 02, 00, 02, 00, 06, 01, 33, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 0f, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 13, 02, 05, 00, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 5 +- expression 0 operands: lhs = Expression(2, Add), rhs = Counter(1) +- expression 1 operands: lhs = Counter(0), rhs = Counter(1) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero +- expression 4 operands: lhs = Expression(0, Sub), rhs = Zero +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 51, 5) to (start + 10, 54) +- Code(Expression(0, Sub)) at (prev + 13, 32) to (start + 0, 35) + = ((c0 + c1) - c1) +- Code(Expression(2, Add)) at (prev + 0, 39) to (start + 0, 73) + = (c0 + c1) +- Code(Expression(3, Add)) at (prev + 1, 23) to (start + 0, 26) + = (((c0 + c1) - c1) + Zero) +- Code(Counter(1)) at (prev + 1, 14) to (start + 0, 15) +- Code(Expression(4, Add)) at (prev + 2, 5) to (start + 0, 6) + = (((c0 + c1) - c1) + Zero) + +Function name: async2::executor::block_on:: +Raw bytes (44): 0x[01, 01, 05, 0b, 05, 01, 05, 01, 05, 02, 00, 02, 00, 06, 01, 33, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 0f, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 13, 02, 05, 00, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 5 +- expression 0 operands: lhs = Expression(2, Add), rhs = Counter(1) +- expression 1 operands: lhs = Counter(0), rhs = Counter(1) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero +- expression 4 operands: lhs = Expression(0, Sub), rhs = Zero +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 51, 5) to (start + 10, 54) +- Code(Expression(0, Sub)) at (prev + 13, 32) to (start + 0, 35) + = ((c0 + c1) - c1) +- Code(Expression(2, Add)) at (prev + 0, 39) to (start + 0, 73) + = (c0 + c1) +- Code(Expression(3, Add)) at (prev + 1, 23) to (start + 0, 26) + = (((c0 + c1) - c1) + Zero) +- Code(Counter(1)) at (prev + 1, 14) to (start + 0, 15) +- Code(Expression(4, Add)) at (prev + 2, 5) to (start + 0, 6) + = (((c0 + c1) - c1) + Zero) + +Function name: async2::executor::block_on::VTABLE::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 37, 11, 00, 33] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 55, 17) to (start + 0, 51) + +Function name: async2::executor::block_on::VTABLE::{closure#1} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 38, 11, 00, 33] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 56, 17) to (start + 0, 51) + +Function name: async2::executor::block_on::VTABLE::{closure#2} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 39, 11, 00, 33] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 57, 17) to (start + 0, 51) + +Function name: async2::executor::block_on::VTABLE::{closure#3} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 3a, 11, 00, 13] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 58, 17) to (start + 0, 19) + +Function name: async2::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 01, 07, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 35, 1) to (start + 7, 2) + +Function name: async2::non_async_func +Raw bytes (26): 0x[01, 01, 01, 05, 00, 04, 01, 09, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 03, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(1), rhs = Zero +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 9, 1) to (start + 3, 9) +- Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(0, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + Zero) + diff --git a/tests/coverage-map/status-quo/async2.rs b/tests/coverage-map/status-quo/async2.rs new file mode 100644 index 0000000000000..959d48ce9db16 --- /dev/null +++ b/tests/coverage-map/status-quo/async2.rs @@ -0,0 +1,69 @@ +// compile-flags: --edition=2018 + +use core::{ + future::Future, + marker::Send, + pin::Pin, +}; + +fn non_async_func() { + println!("non_async_func was covered"); + let b = true; + if b { + println!("non_async_func println in block"); + } +} + + + + +async fn async_func() { + println!("async_func was covered"); + let b = true; + if b { + println!("async_func println in block"); + } +} + + + + +async fn async_func_just_println() { + println!("async_func_just_println was covered"); +} + +fn main() { + println!("codecovsample::main"); + + non_async_func(); + + executor::block_on(async_func()); + executor::block_on(async_func_just_println()); +} + +mod executor { + use core::{ + future::Future, + pin::Pin, + task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, + }; + + pub fn block_on(mut future: F) -> F::Output { + let mut future = unsafe { Pin::new_unchecked(&mut future) }; + use std::hint::unreachable_unchecked; + static VTABLE: RawWakerVTable = RawWakerVTable::new( + |_| unsafe { unreachable_unchecked() }, // clone + |_| unsafe { unreachable_unchecked() }, // wake + |_| unsafe { unreachable_unchecked() }, // wake_by_ref + |_| (), + ); + let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; + let mut context = Context::from_waker(&waker); + + loop { + if let Poll::Ready(val) = future.as_mut().poll(&mut context) { + break val; + } + } + } +} diff --git a/tests/coverage-map/status-quo/conditions.cov-map b/tests/coverage-map/status-quo/conditions.cov-map new file mode 100644 index 0000000000000..2c2ece508b0dc --- /dev/null +++ b/tests/coverage-map/status-quo/conditions.cov-map @@ -0,0 +1,186 @@ +Function name: conditions::main +Raw bytes (564): 0x[01, 01, 4f, 09, 1b, 2d, 31, 05, 00, bb, 02, 09, 05, 00, 0d, 39, 2d, 31, b6, 02, 0d, bb, 02, 09, 05, 00, 03, 00, 35, 00, 53, 3d, 35, 00, 4e, 29, 53, 3d, 35, 00, 4a, 51, 4e, 29, 53, 3d, 35, 00, 45, 49, 3d, 5f, 45, 49, 55, 00, 87, 01, 59, 55, 00, 82, 01, 25, 87, 01, 59, 55, 00, 7e, 79, 82, 01, 25, 87, 01, 59, 55, 00, 5d, 61, 93, 01, 00, 59, 97, 01, 5d, 61, 6d, 8f, 02, 71, 75, 65, 00, c7, 01, 6d, 65, 00, c2, 01, 21, c7, 01, 6d, 65, 00, be, 01, 7d, c2, 01, 21, c7, 01, 6d, 65, 00, 71, 75, 11, 9f, 02, 15, 19, 8b, 02, 00, 6d, 8f, 02, 71, 75, 8b, 02, 11, 6d, 8f, 02, 71, 75, 86, 02, 1d, 8b, 02, 11, 6d, 8f, 02, 71, 75, 82, 02, 89, 01, 86, 02, 1d, 8b, 02, 11, 6d, 8f, 02, 71, 75, 15, 19, 9b, 02, a3, 02, 11, 9f, 02, 15, 19, a7, 02, b2, 02, ab, 02, af, 02, 1d, 21, 25, 29, b6, 02, 0d, bb, 02, 09, 05, 00, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 03, 09, 00, 0a, bb, 02, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, b6, 02, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 16, 00, 1d, 00, 2a, 41, 00, 2e, 00, 3c, 2d, 00, 3d, 02, 0a, 31, 02, 0a, 00, 0b, 1b, 01, 09, 01, 12, b2, 02, 03, 09, 00, 0f, 2b, 03, 09, 01, 0c, 35, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 53, 02, 08, 00, 15, 3d, 00, 16, 02, 06, 4e, 02, 0f, 00, 1c, 4a, 01, 0c, 00, 19, 46, 00, 1d, 00, 2a, 69, 00, 2e, 00, 3c, 45, 00, 3d, 02, 0a, 49, 02, 0a, 00, 0b, 5f, 01, 09, 00, 17, 29, 02, 09, 00, 0f, 5b, 03, 08, 00, 0c, 4d, 01, 0d, 01, 10, 55, 01, 11, 02, 0a, 00, 02, 0a, 00, 0b, 87, 01, 02, 0c, 00, 19, 59, 00, 1a, 02, 0a, 82, 01, 03, 11, 00, 1e, 7e, 01, 10, 00, 1d, 7a, 00, 21, 00, 2e, 81, 01, 00, 32, 00, 40, 5d, 00, 41, 02, 0e, 61, 02, 0e, 00, 0f, 97, 01, 01, 0d, 00, 1b, 25, 02, 0d, 00, 13, 00, 02, 06, 00, 07, 8f, 01, 03, 09, 01, 0c, 65, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 8b, 02, 02, 09, 00, 0a, c7, 01, 00, 10, 00, 1d, 6d, 00, 1e, 02, 06, c2, 01, 02, 0f, 00, 1c, be, 01, 01, 0c, 00, 19, ba, 01, 00, 1d, 00, 2a, 85, 01, 00, 2e, 00, 3c, 71, 00, 3d, 02, 0a, 75, 02, 0a, 00, 0b, 8f, 02, 01, 09, 00, 17, 21, 02, 0d, 02, 0f, 9b, 02, 05, 09, 00, 0a, d7, 01, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, 86, 02, 02, 0f, 00, 1c, 82, 02, 01, 0c, 00, 19, fe, 01, 00, 1d, 00, 2a, 8d, 01, 00, 2e, 00, 3c, 15, 00, 3d, 02, 0a, 19, 02, 0a, 00, 0b, 9f, 02, 01, 09, 00, 17, 1d, 02, 09, 00, 0f, 97, 02, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 79 +- expression 0 operands: lhs = Counter(2), rhs = Expression(6, Add) +- expression 1 operands: lhs = Counter(11), rhs = Counter(12) +- expression 2 operands: lhs = Counter(1), rhs = Zero +- expression 3 operands: lhs = Expression(78, Add), rhs = Counter(2) +- expression 4 operands: lhs = Counter(1), rhs = Zero +- expression 5 operands: lhs = Counter(3), rhs = Counter(14) +- expression 6 operands: lhs = Counter(11), rhs = Counter(12) +- expression 7 operands: lhs = Expression(77, Sub), rhs = Counter(3) +- expression 8 operands: lhs = Expression(78, Add), rhs = Counter(2) +- expression 9 operands: lhs = Counter(1), rhs = Zero +- expression 10 operands: lhs = Expression(0, Add), rhs = Zero +- expression 11 operands: lhs = Counter(13), rhs = Zero +- expression 12 operands: lhs = Expression(20, Add), rhs = Counter(15) +- expression 13 operands: lhs = Counter(13), rhs = Zero +- expression 14 operands: lhs = Expression(19, Sub), rhs = Counter(10) +- expression 15 operands: lhs = Expression(20, Add), rhs = Counter(15) +- expression 16 operands: lhs = Counter(13), rhs = Zero +- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(20) +- expression 18 operands: lhs = Expression(19, Sub), rhs = Counter(10) +- expression 19 operands: lhs = Expression(20, Add), rhs = Counter(15) +- expression 20 operands: lhs = Counter(13), rhs = Zero +- expression 21 operands: lhs = Counter(17), rhs = Counter(18) +- expression 22 operands: lhs = Counter(15), rhs = Expression(23, Add) +- expression 23 operands: lhs = Counter(17), rhs = Counter(18) +- expression 24 operands: lhs = Counter(21), rhs = Zero +- expression 25 operands: lhs = Expression(33, Add), rhs = Counter(22) +- expression 26 operands: lhs = Counter(21), rhs = Zero +- expression 27 operands: lhs = Expression(32, Sub), rhs = Counter(9) +- expression 28 operands: lhs = Expression(33, Add), rhs = Counter(22) +- expression 29 operands: lhs = Counter(21), rhs = Zero +- expression 30 operands: lhs = Expression(31, Sub), rhs = Counter(30) +- expression 31 operands: lhs = Expression(32, Sub), rhs = Counter(9) +- expression 32 operands: lhs = Expression(33, Add), rhs = Counter(22) +- expression 33 operands: lhs = Counter(21), rhs = Zero +- expression 34 operands: lhs = Counter(23), rhs = Counter(24) +- expression 35 operands: lhs = Expression(36, Add), rhs = Zero +- expression 36 operands: lhs = Counter(22), rhs = Expression(37, Add) +- expression 37 operands: lhs = Counter(23), rhs = Counter(24) +- expression 38 operands: lhs = Counter(27), rhs = Expression(67, Add) +- expression 39 operands: lhs = Counter(28), rhs = Counter(29) +- expression 40 operands: lhs = Counter(25), rhs = Zero +- expression 41 operands: lhs = Expression(49, Add), rhs = Counter(27) +- expression 42 operands: lhs = Counter(25), rhs = Zero +- expression 43 operands: lhs = Expression(48, Sub), rhs = Counter(8) +- expression 44 operands: lhs = Expression(49, Add), rhs = Counter(27) +- expression 45 operands: lhs = Counter(25), rhs = Zero +- expression 46 operands: lhs = Expression(47, Sub), rhs = Counter(31) +- expression 47 operands: lhs = Expression(48, Sub), rhs = Counter(8) +- expression 48 operands: lhs = Expression(49, Add), rhs = Counter(27) +- expression 49 operands: lhs = Counter(25), rhs = Zero +- expression 50 operands: lhs = Counter(28), rhs = Counter(29) +- expression 51 operands: lhs = Counter(4), rhs = Expression(71, Add) +- expression 52 operands: lhs = Counter(5), rhs = Counter(6) +- expression 53 operands: lhs = Expression(66, Add), rhs = Zero +- expression 54 operands: lhs = Counter(27), rhs = Expression(67, Add) +- expression 55 operands: lhs = Counter(28), rhs = Counter(29) +- expression 56 operands: lhs = Expression(66, Add), rhs = Counter(4) +- expression 57 operands: lhs = Counter(27), rhs = Expression(67, Add) +- expression 58 operands: lhs = Counter(28), rhs = Counter(29) +- expression 59 operands: lhs = Expression(65, Sub), rhs = Counter(7) +- expression 60 operands: lhs = Expression(66, Add), rhs = Counter(4) +- expression 61 operands: lhs = Counter(27), rhs = Expression(67, Add) +- expression 62 operands: lhs = Counter(28), rhs = Counter(29) +- expression 63 operands: lhs = Expression(64, Sub), rhs = Counter(34) +- expression 64 operands: lhs = Expression(65, Sub), rhs = Counter(7) +- expression 65 operands: lhs = Expression(66, Add), rhs = Counter(4) +- expression 66 operands: lhs = Counter(27), rhs = Expression(67, Add) +- expression 67 operands: lhs = Counter(28), rhs = Counter(29) +- expression 68 operands: lhs = Counter(5), rhs = Counter(6) +- expression 69 operands: lhs = Expression(70, Add), rhs = Expression(72, Add) +- expression 70 operands: lhs = Counter(4), rhs = Expression(71, Add) +- expression 71 operands: lhs = Counter(5), rhs = Counter(6) +- expression 72 operands: lhs = Expression(73, Add), rhs = Expression(76, Sub) +- expression 73 operands: lhs = Expression(74, Add), rhs = Expression(75, Add) +- expression 74 operands: lhs = Counter(7), rhs = Counter(8) +- expression 75 operands: lhs = Counter(9), rhs = Counter(10) +- expression 76 operands: lhs = Expression(77, Sub), rhs = Counter(3) +- expression 77 operands: lhs = Expression(78, Add), rhs = Counter(2) +- expression 78 operands: lhs = Counter(1), rhs = Zero +Number of file 0 mappings: 68 +- Code(Counter(0)) at (prev + 3, 1) to (start + 2, 12) +- Code(Counter(1)) at (prev + 2, 13) to (start + 2, 6) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(0, Add)) at (prev + 3, 9) to (start + 0, 10) + = (c2 + (c11 + c12)) +- Code(Expression(78, Add)) at (prev + 0, 16) to (start + 0, 29) + = (c1 + Zero) +- Code(Counter(2)) at (prev + 1, 9) to (start + 1, 10) +- Code(Expression(77, Sub)) at (prev + 2, 15) to (start + 0, 28) + = ((c1 + Zero) - c2) +- Code(Counter(3)) at (prev + 1, 12) to (start + 0, 25) +- Code(Expression(5, Sub)) at (prev + 0, 29) to (start + 0, 42) + = (c3 - c14) +- Code(Counter(16)) at (prev + 0, 46) to (start + 0, 60) +- Code(Counter(11)) at (prev + 0, 61) to (start + 2, 10) +- Code(Counter(12)) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(6, Add)) at (prev + 1, 9) to (start + 1, 18) + = (c11 + c12) +- Code(Expression(76, Sub)) at (prev + 3, 9) to (start + 0, 15) + = (((c1 + Zero) - c2) - c3) +- Code(Expression(10, Add)) at (prev + 3, 9) to (start + 1, 12) + = ((c2 + (c11 + c12)) + Zero) +- Code(Counter(13)) at (prev + 1, 13) to (start + 2, 6) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(20, Add)) at (prev + 2, 8) to (start + 0, 21) + = (c13 + Zero) +- Code(Counter(15)) at (prev + 0, 22) to (start + 2, 6) +- Code(Expression(19, Sub)) at (prev + 2, 15) to (start + 0, 28) + = ((c13 + Zero) - c15) +- Code(Expression(18, Sub)) at (prev + 1, 12) to (start + 0, 25) + = (((c13 + Zero) - c15) - c10) +- Code(Expression(17, Sub)) at (prev + 0, 29) to (start + 0, 42) + = ((((c13 + Zero) - c15) - c10) - c20) +- Code(Counter(26)) at (prev + 0, 46) to (start + 0, 60) +- Code(Counter(17)) at (prev + 0, 61) to (start + 2, 10) +- Code(Counter(18)) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(23, Add)) at (prev + 1, 9) to (start + 0, 23) + = (c17 + c18) +- Code(Counter(10)) at (prev + 2, 9) to (start + 0, 15) +- Code(Expression(22, Add)) at (prev + 3, 8) to (start + 0, 12) + = (c15 + (c17 + c18)) +- Code(Counter(19)) at (prev + 1, 13) to (start + 1, 16) +- Code(Counter(21)) at (prev + 1, 17) to (start + 2, 10) +- Code(Zero) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(33, Add)) at (prev + 2, 12) to (start + 0, 25) + = (c21 + Zero) +- Code(Counter(22)) at (prev + 0, 26) to (start + 2, 10) +- Code(Expression(32, Sub)) at (prev + 3, 17) to (start + 0, 30) + = ((c21 + Zero) - c22) +- Code(Expression(31, Sub)) at (prev + 1, 16) to (start + 0, 29) + = (((c21 + Zero) - c22) - c9) +- Code(Expression(30, Sub)) at (prev + 0, 33) to (start + 0, 46) + = ((((c21 + Zero) - c22) - c9) - c30) +- Code(Counter(32)) at (prev + 0, 50) to (start + 0, 64) +- Code(Counter(23)) at (prev + 0, 65) to (start + 2, 14) +- Code(Counter(24)) at (prev + 2, 14) to (start + 0, 15) +- Code(Expression(37, Add)) at (prev + 1, 13) to (start + 0, 27) + = (c23 + c24) +- Code(Counter(9)) at (prev + 2, 13) to (start + 0, 19) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(35, Add)) at (prev + 3, 9) to (start + 1, 12) + = ((c22 + (c23 + c24)) + Zero) +- Code(Counter(25)) at (prev + 1, 13) to (start + 2, 6) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(66, Add)) at (prev + 2, 9) to (start + 0, 10) + = (c27 + (c28 + c29)) +- Code(Expression(49, Add)) at (prev + 0, 16) to (start + 0, 29) + = (c25 + Zero) +- Code(Counter(27)) at (prev + 0, 30) to (start + 2, 6) +- Code(Expression(48, Sub)) at (prev + 2, 15) to (start + 0, 28) + = ((c25 + Zero) - c27) +- Code(Expression(47, Sub)) at (prev + 1, 12) to (start + 0, 25) + = (((c25 + Zero) - c27) - c8) +- Code(Expression(46, Sub)) at (prev + 0, 29) to (start + 0, 42) + = ((((c25 + Zero) - c27) - c8) - c31) +- Code(Counter(33)) at (prev + 0, 46) to (start + 0, 60) +- Code(Counter(28)) at (prev + 0, 61) to (start + 2, 10) +- Code(Counter(29)) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(67, Add)) at (prev + 1, 9) to (start + 0, 23) + = (c28 + c29) +- Code(Counter(8)) at (prev + 2, 13) to (start + 2, 15) +- Code(Expression(70, Add)) at (prev + 5, 9) to (start + 0, 10) + = (c4 + (c5 + c6)) +- Code(Expression(53, Add)) at (prev + 0, 16) to (start + 0, 29) + = ((c27 + (c28 + c29)) + Zero) +- Code(Counter(4)) at (prev + 0, 30) to (start + 2, 6) +- Code(Expression(65, Sub)) at (prev + 2, 15) to (start + 0, 28) + = ((c27 + (c28 + c29)) - c4) +- Code(Expression(64, Sub)) at (prev + 1, 12) to (start + 0, 25) + = (((c27 + (c28 + c29)) - c4) - c7) +- Code(Expression(63, Sub)) at (prev + 0, 29) to (start + 0, 42) + = ((((c27 + (c28 + c29)) - c4) - c7) - c34) +- Code(Counter(35)) at (prev + 0, 46) to (start + 0, 60) +- Code(Counter(5)) at (prev + 0, 61) to (start + 2, 10) +- Code(Counter(6)) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(71, Add)) at (prev + 1, 9) to (start + 0, 23) + = (c5 + c6) +- Code(Counter(7)) at (prev + 2, 9) to (start + 0, 15) +- Code(Expression(69, Add)) at (prev + 2, 1) to (start + 0, 2) + = ((c4 + (c5 + c6)) + (((c7 + c8) + (c9 + c10)) + (((c1 + Zero) - c2) - c3))) + diff --git a/tests/coverage-map/status-quo/conditions.rs b/tests/coverage-map/status-quo/conditions.rs new file mode 100644 index 0000000000000..057599d1b471a --- /dev/null +++ b/tests/coverage-map/status-quo/conditions.rs @@ -0,0 +1,87 @@ +#![allow(unused_assignments, unused_variables)] + +fn main() { + let mut countdown = 0; + if true { + countdown = 10; + } + + const B: u32 = 100; + let x = if countdown > 7 { + countdown -= 4; + B + } else if countdown > 2 { + if countdown < 1 || countdown > 5 || countdown != 9 { + countdown = 0; + } + countdown -= 5; + countdown + } else { + return; + }; + + let mut countdown = 0; + if true { + countdown = 10; + } + + if countdown > 7 { + countdown -= 4; + } else if countdown > 2 { + if countdown < 1 || countdown > 5 || countdown != 9 { + countdown = 0; + } + countdown -= 5; + } else { + return; + } + + if true { + let mut countdown = 0; + if true { + countdown = 10; + } + + if countdown > 7 { + countdown -= 4; + } + else if countdown > 2 { + if countdown < 1 || countdown > 5 || countdown != 9 { + countdown = 0; + } + countdown -= 5; + } else { + return; + } + } + + + let mut countdown = 0; + if true { + countdown = 1; + } + + let z = if countdown > 7 { + countdown -= 4; + } else if countdown > 2 { + if countdown < 1 || countdown > 5 || countdown != 9 { + countdown = 0; + } + countdown -= 5; + } else { + let should_be_reachable = countdown; + println!("reached"); + return; + }; + + let w = if countdown > 7 { + countdown -= 4; + } else if countdown > 2 { + if countdown < 1 || countdown > 5 || countdown != 9 { + countdown = 0; + } + countdown -= 5; + } else { + return; + }; +} diff --git a/tests/coverage-map/status-quo/drop_trait.cov-map b/tests/coverage-map/status-quo/drop_trait.cov-map new file mode 100644 index 0000000000000..203d1048b0547 --- /dev/null +++ b/tests/coverage-map/status-quo/drop_trait.cov-map @@ -0,0 +1,21 @@ +Function name: ::drop +Raw bytes (9): 0x[01, 01, 00, 01, 01, 09, 05, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 9, 5) to (start + 2, 6) + +Function name: drop_trait::main +Raw bytes (26): 0x[01, 01, 01, 05, 00, 04, 01, 0e, 01, 05, 0c, 05, 06, 09, 01, 16, 00, 02, 06, 04, 0b, 03, 05, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(1), rhs = Zero +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 14, 1) to (start + 5, 12) +- Code(Counter(1)) at (prev + 6, 9) to (start + 1, 22) +- Code(Zero) at (prev + 2, 6) to (start + 4, 11) +- Code(Expression(0, Add)) at (prev + 5, 1) to (start + 0, 2) + = (c1 + Zero) + diff --git a/tests/coverage-map/status-quo/drop_trait.rs b/tests/coverage-map/status-quo/drop_trait.rs new file mode 100644 index 0000000000000..a9b5d1d1e7fe9 --- /dev/null +++ b/tests/coverage-map/status-quo/drop_trait.rs @@ -0,0 +1,33 @@ +#![allow(unused_assignments)] +// failure-status: 1 + +struct Firework { + strength: i32, +} + +impl Drop for Firework { + fn drop(&mut self) { + println!("BOOM times {}!!!", self.strength); + } +} + +fn main() -> Result<(),u8> { + let _firecracker = Firework { strength: 1 }; + + let _tnt = Firework { strength: 100 }; + + if true { + println!("Exiting with error..."); + return Err(1); + } + + let _ = Firework { strength: 1000 }; + + Ok(()) +} + +// Expected program output: +// Exiting with error... +// BOOM times 100!!! +// BOOM times 1!!! +// Error: 1 diff --git a/tests/coverage-map/status-quo/generics.cov-map b/tests/coverage-map/status-quo/generics.cov-map new file mode 100644 index 0000000000000..c28e9c1fa93f4 --- /dev/null +++ b/tests/coverage-map/status-quo/generics.cov-map @@ -0,0 +1,45 @@ +Function name: as core::ops::drop::Drop>::drop +Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 05, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 17, 5) to (start + 2, 6) + +Function name: >::set_strength +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 05, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 10, 5) to (start + 2, 6) + +Function name: as core::ops::drop::Drop>::drop +Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 05, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 17, 5) to (start + 2, 6) + +Function name: >::set_strength +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 05, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 10, 5) to (start + 2, 6) + +Function name: generics::main +Raw bytes (26): 0x[01, 01, 01, 05, 00, 04, 01, 16, 01, 08, 0c, 05, 09, 09, 01, 16, 00, 02, 06, 08, 0b, 03, 09, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(1), rhs = Zero +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 22, 1) to (start + 8, 12) +- Code(Counter(1)) at (prev + 9, 9) to (start + 1, 22) +- Code(Zero) at (prev + 2, 6) to (start + 8, 11) +- Code(Expression(0, Add)) at (prev + 9, 1) to (start + 0, 2) + = (c1 + Zero) + diff --git a/tests/coverage-map/status-quo/generics.rs b/tests/coverage-map/status-quo/generics.rs new file mode 100644 index 0000000000000..150ffb9db395a --- /dev/null +++ b/tests/coverage-map/status-quo/generics.rs @@ -0,0 +1,48 @@ +#![allow(unused_assignments)] +// failure-status: 1 + +struct Firework where T: Copy + std::fmt::Display { + strength: T, +} + +impl Firework where T: Copy + std::fmt::Display { + #[inline(always)] + fn set_strength(&mut self, new_strength: T) { + self.strength = new_strength; + } +} + +impl Drop for Firework where T: Copy + std::fmt::Display { + #[inline(always)] + fn drop(&mut self) { + println!("BOOM times {}!!!", self.strength); + } +} + +fn main() -> Result<(),u8> { + let mut firecracker = Firework { strength: 1 }; + firecracker.set_strength(2); + + let mut tnt = Firework { strength: 100.1 }; + tnt.set_strength(200.1); + tnt.set_strength(300.3); + + if true { + println!("Exiting with error..."); + return Err(1); + } + + + + + + let _ = Firework { strength: 1000 }; + + Ok(()) +} + +// Expected program output: +// Exiting with error... +// BOOM times 100!!! +// BOOM times 1!!! +// Error: 1 diff --git a/tests/coverage-map/status-quo/loops_branches.cov-map b/tests/coverage-map/status-quo/loops_branches.cov-map new file mode 100644 index 0000000000000..ef1aeae97411a --- /dev/null +++ b/tests/coverage-map/status-quo/loops_branches.cov-map @@ -0,0 +1,193 @@ +Function name: ::fmt +Raw bytes (262): 0x[01, 01, 36, 05, 09, 0a, 02, 00, 00, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, d3, 01, d7, 01, 0d, 00, 11, 15, ca, 01, 00, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, c6, 01, 1d, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, be, 01, c2, 01, 00, 00, c6, 01, 1d, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, bb, 01, 11, be, 01, c2, 01, 00, 00, c6, 01, 1d, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, 25, b3, 01, b6, 01, 19, bb, 01, 11, be, 01, c2, 01, 00, 00, c6, 01, 1d, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 01, 12, 02, 02, 0e, 00, 0f, 07, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, ca, 01, 03, 0d, 00, 0e, cf, 01, 00, 12, 00, 17, 2b, 01, 10, 00, 14, c6, 01, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, c2, 01, 01, 12, 00, 13, bb, 01, 01, 11, 00, 22, b6, 01, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, af, 01, 01, 05, 00, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 54 +- expression 0 operands: lhs = Counter(1), rhs = Counter(2) +- expression 1 operands: lhs = Expression(2, Sub), rhs = Expression(0, Sub) +- expression 2 operands: lhs = Zero, rhs = Zero +- expression 3 operands: lhs = Expression(51, Add), rhs = Counter(6) +- expression 4 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 5 operands: lhs = Counter(3), rhs = Zero +- expression 6 operands: lhs = Counter(4), rhs = Counter(5) +- expression 7 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 8 operands: lhs = Counter(3), rhs = Zero +- expression 9 operands: lhs = Counter(4), rhs = Counter(5) +- expression 10 operands: lhs = Expression(50, Sub), rhs = Zero +- expression 11 operands: lhs = Expression(51, Add), rhs = Counter(6) +- expression 12 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 13 operands: lhs = Counter(3), rhs = Zero +- expression 14 operands: lhs = Counter(4), rhs = Counter(5) +- expression 15 operands: lhs = Expression(50, Sub), rhs = Counter(5) +- expression 16 operands: lhs = Expression(51, Add), rhs = Counter(6) +- expression 17 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 18 operands: lhs = Counter(3), rhs = Zero +- expression 19 operands: lhs = Counter(4), rhs = Counter(5) +- expression 20 operands: lhs = Expression(49, Sub), rhs = Counter(7) +- expression 21 operands: lhs = Expression(50, Sub), rhs = Counter(5) +- expression 22 operands: lhs = Expression(51, Add), rhs = Counter(6) +- expression 23 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 24 operands: lhs = Counter(3), rhs = Zero +- expression 25 operands: lhs = Counter(4), rhs = Counter(5) +- expression 26 operands: lhs = Expression(47, Sub), rhs = Expression(48, Sub) +- expression 27 operands: lhs = Zero, rhs = Zero +- expression 28 operands: lhs = Expression(49, Sub), rhs = Counter(7) +- expression 29 operands: lhs = Expression(50, Sub), rhs = Counter(5) +- expression 30 operands: lhs = Expression(51, Add), rhs = Counter(6) +- expression 31 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 32 operands: lhs = Counter(3), rhs = Zero +- expression 33 operands: lhs = Counter(4), rhs = Counter(5) +- expression 34 operands: lhs = Expression(46, Add), rhs = Counter(4) +- expression 35 operands: lhs = Expression(47, Sub), rhs = Expression(48, Sub) +- expression 36 operands: lhs = Zero, rhs = Zero +- expression 37 operands: lhs = Expression(49, Sub), rhs = Counter(7) +- expression 38 operands: lhs = Expression(50, Sub), rhs = Counter(5) +- expression 39 operands: lhs = Expression(51, Add), rhs = Counter(6) +- expression 40 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 41 operands: lhs = Counter(3), rhs = Zero +- expression 42 operands: lhs = Counter(4), rhs = Counter(5) +- expression 43 operands: lhs = Counter(9), rhs = Expression(44, Add) +- expression 44 operands: lhs = Expression(45, Sub), rhs = Counter(6) +- expression 45 operands: lhs = Expression(46, Add), rhs = Counter(4) +- expression 46 operands: lhs = Expression(47, Sub), rhs = Expression(48, Sub) +- expression 47 operands: lhs = Zero, rhs = Zero +- expression 48 operands: lhs = Expression(49, Sub), rhs = Counter(7) +- expression 49 operands: lhs = Expression(50, Sub), rhs = Counter(5) +- expression 50 operands: lhs = Expression(51, Add), rhs = Counter(6) +- expression 51 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) +- expression 52 operands: lhs = Counter(3), rhs = Zero +- expression 53 operands: lhs = Counter(4), rhs = Counter(5) +Number of file 0 mappings: 20 +- Code(Counter(0)) at (prev + 9, 5) to (start + 1, 16) +- Code(Counter(1)) at (prev + 2, 16) to (start + 0, 21) +- Code(Zero) at (prev + 1, 23) to (start + 0, 27) +- Code(Zero) at (prev + 0, 28) to (start + 1, 18) +- Code(Expression(0, Sub)) at (prev + 2, 14) to (start + 0, 15) + = (c1 - c2) +- Code(Expression(1, Add)) at (prev + 1, 13) to (start + 0, 30) + = ((Zero - Zero) + (c1 - c2)) +- Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31) +- Code(Zero) at (prev + 1, 16) to (start + 1, 10) +- Code(Expression(50, Sub)) at (prev + 3, 13) to (start + 0, 14) + = (((c3 + Zero) + (c4 + c5)) - c6) +- Code(Expression(51, Add)) at (prev + 0, 18) to (start + 0, 23) + = ((c3 + Zero) + (c4 + c5)) +- Code(Expression(10, Add)) at (prev + 1, 16) to (start + 0, 20) + = ((((c3 + Zero) + (c4 + c5)) - c6) + Zero) +- Code(Expression(49, Sub)) at (prev + 1, 20) to (start + 0, 25) + = ((((c3 + Zero) + (c4 + c5)) - c6) - c5) +- Code(Zero) at (prev + 1, 27) to (start + 0, 31) +- Code(Zero) at (prev + 0, 32) to (start + 0, 34) +- Code(Expression(48, Sub)) at (prev + 1, 18) to (start + 0, 19) + = (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7) +- Code(Expression(46, Add)) at (prev + 1, 17) to (start + 0, 34) + = ((Zero - Zero) + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) +- Code(Expression(45, Sub)) at (prev + 0, 34) to (start + 0, 35) + = (((Zero - Zero) + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) - c4) +- Code(Zero) at (prev + 1, 20) to (start + 1, 14) +- Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) +- Code(Expression(43, Add)) at (prev + 1, 5) to (start + 0, 6) + = (c9 + ((((Zero - Zero) + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) - c4) + c6)) + +Function name: ::fmt +Raw bytes (266): 0x[01, 01, 38, 01, 05, 02, 09, 0e, 12, 00, 00, 02, 09, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, d7, 01, db, 01, 05, 0d, 11, 15, ce, 01, 00, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, ca, 01, 1d, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, c2, 01, c6, 01, 00, 00, ca, 01, 1d, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, bf, 01, 15, c2, 01, c6, 01, 00, 00, ca, 01, 1d, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, ba, 01, df, 01, bf, 01, 15, c2, 01, c6, 01, 00, 00, ca, 01, 1d, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, 19, 25, 14, 01, 23, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 12, 01, 0e, 00, 0f, 0b, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, ce, 01, 02, 0d, 00, 0e, d3, 01, 00, 12, 00, 17, 33, 01, 10, 00, 15, 00, 00, 16, 01, 0e, ca, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, c6, 01, 01, 12, 00, 13, bf, 01, 01, 11, 00, 22, ba, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, b7, 01, 01, 05, 00, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 56 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Expression(0, Sub), rhs = Counter(2) +- expression 2 operands: lhs = Expression(3, Sub), rhs = Expression(4, Sub) +- expression 3 operands: lhs = Zero, rhs = Zero +- expression 4 operands: lhs = Expression(0, Sub), rhs = Counter(2) +- expression 5 operands: lhs = Expression(52, Add), rhs = Counter(6) +- expression 6 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) +- expression 7 operands: lhs = Counter(1), rhs = Counter(3) +- expression 8 operands: lhs = Counter(4), rhs = Counter(5) +- expression 9 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) +- expression 10 operands: lhs = Counter(1), rhs = Counter(3) +- expression 11 operands: lhs = Counter(4), rhs = Counter(5) +- expression 12 operands: lhs = Expression(51, Sub), rhs = Zero +- expression 13 operands: lhs = Expression(52, Add), rhs = Counter(6) +- expression 14 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) +- expression 15 operands: lhs = Counter(1), rhs = Counter(3) +- expression 16 operands: lhs = Counter(4), rhs = Counter(5) +- expression 17 operands: lhs = Expression(51, Sub), rhs = Counter(4) +- expression 18 operands: lhs = Expression(52, Add), rhs = Counter(6) +- expression 19 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) +- expression 20 operands: lhs = Counter(1), rhs = Counter(3) +- expression 21 operands: lhs = Counter(4), rhs = Counter(5) +- expression 22 operands: lhs = Expression(50, Sub), rhs = Counter(7) +- expression 23 operands: lhs = Expression(51, Sub), rhs = Counter(4) +- expression 24 operands: lhs = Expression(52, Add), rhs = Counter(6) +- expression 25 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) +- expression 26 operands: lhs = Counter(1), rhs = Counter(3) +- expression 27 operands: lhs = Counter(4), rhs = Counter(5) +- expression 28 operands: lhs = Expression(48, Sub), rhs = Expression(49, Sub) +- expression 29 operands: lhs = Zero, rhs = Zero +- expression 30 operands: lhs = Expression(50, Sub), rhs = Counter(7) +- expression 31 operands: lhs = Expression(51, Sub), rhs = Counter(4) +- expression 32 operands: lhs = Expression(52, Add), rhs = Counter(6) +- expression 33 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) +- expression 34 operands: lhs = Counter(1), rhs = Counter(3) +- expression 35 operands: lhs = Counter(4), rhs = Counter(5) +- expression 36 operands: lhs = Expression(47, Add), rhs = Counter(5) +- expression 37 operands: lhs = Expression(48, Sub), rhs = Expression(49, Sub) +- expression 38 operands: lhs = Zero, rhs = Zero +- expression 39 operands: lhs = Expression(50, Sub), rhs = Counter(7) +- expression 40 operands: lhs = Expression(51, Sub), rhs = Counter(4) +- expression 41 operands: lhs = Expression(52, Add), rhs = Counter(6) +- expression 42 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) +- expression 43 operands: lhs = Counter(1), rhs = Counter(3) +- expression 44 operands: lhs = Counter(4), rhs = Counter(5) +- expression 45 operands: lhs = Expression(46, Sub), rhs = Expression(55, Add) +- expression 46 operands: lhs = Expression(47, Add), rhs = Counter(5) +- expression 47 operands: lhs = Expression(48, Sub), rhs = Expression(49, Sub) +- expression 48 operands: lhs = Zero, rhs = Zero +- expression 49 operands: lhs = Expression(50, Sub), rhs = Counter(7) +- expression 50 operands: lhs = Expression(51, Sub), rhs = Counter(4) +- expression 51 operands: lhs = Expression(52, Add), rhs = Counter(6) +- expression 52 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) +- expression 53 operands: lhs = Counter(1), rhs = Counter(3) +- expression 54 operands: lhs = Counter(4), rhs = Counter(5) +- expression 55 operands: lhs = Counter(6), rhs = Counter(9) +Number of file 0 mappings: 20 +- Code(Counter(0)) at (prev + 35, 5) to (start + 1, 17) +- Code(Zero) at (prev + 1, 18) to (start + 1, 10) +- Code(Expression(0, Sub)) at (prev + 2, 16) to (start + 0, 21) + = (c0 - c1) +- Code(Zero) at (prev + 1, 23) to (start + 0, 27) +- Code(Zero) at (prev + 0, 28) to (start + 0, 30) +- Code(Expression(4, Sub)) at (prev + 1, 14) to (start + 0, 15) + = ((c0 - c1) - c2) +- Code(Expression(2, Add)) at (prev + 1, 13) to (start + 0, 30) + = ((Zero - Zero) + ((c0 - c1) - c2)) +- Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31) +- Code(Expression(51, Sub)) at (prev + 2, 13) to (start + 0, 14) + = (((c1 + c3) + (c4 + c5)) - c6) +- Code(Expression(52, Add)) at (prev + 0, 18) to (start + 0, 23) + = ((c1 + c3) + (c4 + c5)) +- Code(Expression(12, Add)) at (prev + 1, 16) to (start + 0, 21) + = ((((c1 + c3) + (c4 + c5)) - c6) + Zero) +- Code(Zero) at (prev + 0, 22) to (start + 1, 14) +- Code(Expression(50, Sub)) at (prev + 2, 20) to (start + 0, 25) + = ((((c1 + c3) + (c4 + c5)) - c6) - c4) +- Code(Zero) at (prev + 1, 27) to (start + 0, 31) +- Code(Zero) at (prev + 0, 32) to (start + 0, 34) +- Code(Expression(49, Sub)) at (prev + 1, 18) to (start + 0, 19) + = (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7) +- Code(Expression(47, Add)) at (prev + 1, 17) to (start + 0, 34) + = ((Zero - Zero) + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) +- Code(Expression(46, Sub)) at (prev + 0, 34) to (start + 0, 35) + = (((Zero - Zero) + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) - c5) +- Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) +- Code(Expression(45, Add)) at (prev + 1, 5) to (start + 0, 6) + = ((((Zero - Zero) + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) - c5) + (c6 + c9)) + +Function name: loops_branches::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 38, 01, 05, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 56, 1) to (start + 5, 2) + diff --git a/tests/coverage-map/status-quo/loops_branches.rs b/tests/coverage-map/status-quo/loops_branches.rs new file mode 100644 index 0000000000000..7116ce47f4b9d --- /dev/null +++ b/tests/coverage-map/status-quo/loops_branches.rs @@ -0,0 +1,61 @@ +#![allow(unused_assignments, unused_variables, while_true)] + +// This test confirms that (1) unexecuted infinite loops are handled correctly by the +// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped. + +struct DebugTest; + +impl std::fmt::Debug for DebugTest { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + if true { + if false { + while true { + } + } + write!(f, "cool")?; + } else { + } + + for i in 0..10 { + if true { + if false { + while true {} + } + write!(f, "cool")?; + } else { + } + } + Ok(()) + } +} + +struct DisplayTest; + +impl std::fmt::Display for DisplayTest { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + if false { + } else { + if false { + while true {} + } + write!(f, "cool")?; + } + for i in 0..10 { + if false { + } else { + if false { + while true {} + } + write!(f, "cool")?; + } + } + Ok(()) + } +} + +fn main() { + let debug_test = DebugTest; + println!("{:?}", debug_test); + let display_test = DisplayTest; + println!("{}", display_test); +} diff --git a/tests/coverage-map/status-quo/unused.cov-map b/tests/coverage-map/status-quo/unused.cov-map new file mode 100644 index 0000000000000..84bbb2c262b06 --- /dev/null +++ b/tests/coverage-map/status-quo/unused.cov-map @@ -0,0 +1,94 @@ +Function name: unused::foo:: +Raw bytes (42): 0x[01, 01, 04, 01, 0f, 05, 09, 03, 0d, 05, 09, 06, 01, 01, 01, 01, 12, 03, 02, 0b, 00, 11, 0a, 01, 09, 00, 0f, 09, 00, 13, 00, 19, 0f, 01, 09, 00, 0f, 0d, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Counter(0), rhs = Expression(3, Add) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 3 operands: lhs = Counter(1), rhs = Counter(2) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 1, 1) to (start + 1, 18) +- Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 17) + = (c0 + (c1 + c2)) +- Code(Expression(2, Sub)) at (prev + 1, 9) to (start + 0, 15) + = ((c0 + (c1 + c2)) - c3) +- Code(Counter(2)) at (prev + 0, 19) to (start + 0, 25) +- Code(Expression(3, Add)) at (prev + 1, 9) to (start + 0, 15) + = (c1 + c2) +- Code(Counter(3)) at (prev + 2, 1) to (start + 0, 2) + +Function name: unused::foo:: +Raw bytes (42): 0x[01, 01, 04, 01, 0f, 05, 09, 03, 0d, 05, 09, 06, 01, 01, 01, 01, 12, 03, 02, 0b, 00, 11, 0a, 01, 09, 00, 0f, 09, 00, 13, 00, 19, 0f, 01, 09, 00, 0f, 0d, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Counter(0), rhs = Expression(3, Add) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 3 operands: lhs = Counter(1), rhs = Counter(2) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 1, 1) to (start + 1, 18) +- Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 17) + = (c0 + (c1 + c2)) +- Code(Expression(2, Sub)) at (prev + 1, 9) to (start + 0, 15) + = ((c0 + (c1 + c2)) - c3) +- Code(Counter(2)) at (prev + 0, 19) to (start + 0, 25) +- Code(Expression(3, Add)) at (prev + 1, 9) to (start + 0, 15) + = (c1 + c2) +- Code(Counter(3)) at (prev + 2, 1) to (start + 0, 2) + +Function name: unused::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 01, 04, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 35, 1) to (start + 4, 2) + +Function name: unused::unused_func (unused) +Raw bytes (24): 0x[01, 01, 00, 04, 01, 11, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 17, 1) to (start + 1, 14) +- Code(Zero) at (prev + 1, 15) to (start + 2, 6) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 1, 1) to (start + 0, 2) + +Function name: unused::unused_func2 (unused) +Raw bytes (24): 0x[01, 01, 00, 04, 01, 17, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 23, 1) to (start + 1, 14) +- Code(Zero) at (prev + 1, 15) to (start + 2, 6) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 1, 1) to (start + 0, 2) + +Function name: unused::unused_func3 (unused) +Raw bytes (24): 0x[01, 01, 00, 04, 01, 1d, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 29, 1) to (start + 1, 14) +- Code(Zero) at (prev + 1, 15) to (start + 2, 6) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 1, 1) to (start + 0, 2) + +Function name: unused::unused_template_func::<_> (unused) +Raw bytes (34): 0x[01, 01, 00, 06, 01, 09, 01, 01, 12, 00, 02, 0b, 00, 11, 00, 01, 09, 00, 0f, 00, 00, 13, 00, 19, 00, 01, 09, 00, 0f, 00, 02, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 9, 1) to (start + 1, 18) +- Code(Zero) at (prev + 2, 11) to (start + 0, 17) +- Code(Zero) at (prev + 1, 9) to (start + 0, 15) +- Code(Zero) at (prev + 0, 19) to (start + 0, 25) +- Code(Zero) at (prev + 1, 9) to (start + 0, 15) +- Code(Zero) at (prev + 2, 1) to (start + 0, 2) + diff --git a/tests/coverage-map/status-quo/unused.rs b/tests/coverage-map/status-quo/unused.rs new file mode 100644 index 0000000000000..fb6113eb01c2d --- /dev/null +++ b/tests/coverage-map/status-quo/unused.rs @@ -0,0 +1,39 @@ +fn foo(x: T) { + let mut i = 0; + while i < 10 { + i != 0 || i != 0; + i += 1; + } +} + +fn unused_template_func(x: T) { + let mut i = 0; + while i < 10 { + i != 0 || i != 0; + i += 1; + } +} + +fn unused_func(mut a: u32) { + if a != 0 { + a += 1; + } +} + +fn unused_func2(mut a: u32) { + if a != 0 { + a += 1; + } +} + +fn unused_func3(mut a: u32) { + if a != 0 { + a += 1; + } +} + +fn main() -> Result<(), u8> { + foo::(0); + foo::(0.0); + Ok(()) +} From f268c0a1fa2b69c91d10fc93db3598beb2417b7d Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 2 Aug 2023 15:55:37 +1000 Subject: [PATCH 04/11] coverage: Make the zero counter a constant --- .../src/coverageinfo/ffi.rs | 19 ++++++++----------- .../src/coverageinfo/map_data.rs | 8 ++++---- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 7a82d05ce9ea2..fe334b292657d 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -30,11 +30,8 @@ pub struct Counter { } impl Counter { - /// Constructs a new `Counter` of kind `Zero`. For this `CounterKind`, the - /// `id` is not used. - pub fn zero() -> Self { - Self { kind: CounterKind::Zero, id: 0 } - } + /// A `Counter` of kind `Zero`. For this counter kind, the `id` is not used. + pub(crate) const ZERO: Self = Self { kind: CounterKind::Zero, id: 0 }; /// Constructs a new `Counter` of kind `CounterValueReference`. pub fn counter_value_reference(counter_id: CounterId) -> Self { @@ -172,7 +169,7 @@ impl CounterMappingRegion { ) -> Self { Self { counter, - false_counter: Counter::zero(), + false_counter: Counter::ZERO, file_id, expanded_file_id: 0, start_line, @@ -220,8 +217,8 @@ impl CounterMappingRegion { end_col: u32, ) -> Self { Self { - counter: Counter::zero(), - false_counter: Counter::zero(), + counter: Counter::ZERO, + false_counter: Counter::ZERO, file_id, expanded_file_id, start_line, @@ -243,8 +240,8 @@ impl CounterMappingRegion { end_col: u32, ) -> Self { Self { - counter: Counter::zero(), - false_counter: Counter::zero(), + counter: Counter::ZERO, + false_counter: Counter::ZERO, file_id, expanded_file_id: 0, start_line, @@ -268,7 +265,7 @@ impl CounterMappingRegion { ) -> Self { Self { counter, - false_counter: Counter::zero(), + false_counter: Counter::ZERO, file_id, expanded_file_id: 0, start_line, diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index f1e68af25d406..cf0de817f486a 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -191,7 +191,7 @@ impl<'tcx> FunctionCoverage<'tcx> { // vector is only complete up to the current `ExpressionIndex`. type NewIndexes = IndexSlice>; let id_to_counter = |new_indexes: &NewIndexes, operand: Operand| match operand { - Operand::Zero => Some(Counter::zero()), + Operand::Zero => Some(Counter::ZERO), Operand::Counter(id) => Some(Counter::counter_value_reference(id)), Operand::Expression(id) => { self.expressions @@ -201,7 +201,7 @@ impl<'tcx> FunctionCoverage<'tcx> { // If an expression was optimized out, assume it would have produced a count // of zero. This ensures that expressions dependent on optimized-out // expressions are still valid. - .map_or(Some(Counter::zero()), |_| new_indexes[id].map(Counter::expression)) + .map_or(Some(Counter::ZERO), |_| new_indexes[id].map(Counter::expression)) } }; @@ -237,7 +237,7 @@ impl<'tcx> FunctionCoverage<'tcx> { original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}", original_index, lhs, op, rhs, optional_region, ); - rhs_counter = Counter::zero(); + rhs_counter = Counter::ZERO; } debug_assert!( lhs_counter.is_zero() @@ -306,6 +306,6 @@ impl<'tcx> FunctionCoverage<'tcx> { } fn unreachable_regions(&self) -> impl Iterator { - self.unreachable_regions.iter().map(|region| (Counter::zero(), region)) + self.unreachable_regions.iter().map(|region| (Counter::ZERO, region)) } } From f39b2468a85bc1c1fd3a31e7bcbca5f6f8ce481b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 14 Aug 2023 18:01:28 +1000 Subject: [PATCH 05/11] coverage: Explicitly simplify coverage expressions in codegen After coverage instrumentation and MIR transformations, we can sometimes end up with coverage expressions that always have a value of zero. Any expression operand that refers to an always-zero expression can be replaced with a literal `Operand::Zero`, making the emitted coverage mapping data smaller and simpler. This simplification step is mostly redundant with the simplifications performed inline in `expressions_with_regions`, except that it does a slightly more thorough job in some cases (because it checks for always-zero expressions *after* other simplifications). However, adding this simplification step will then let us greatly simplify that code, without affecting the quality of the emitted coverage maps. --- .../src/coverageinfo/map_data.rs | 49 ++++ .../src/coverageinfo/mapgen.rs | 4 +- .../status-quo/loops_branches.cov-map | 264 +++++++++--------- 3 files changed, 180 insertions(+), 137 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index cf0de817f486a..cabf3cea592f3 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -1,5 +1,6 @@ use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; +use rustc_data_structures::fx::FxIndexSet; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::bug; use rustc_middle::mir::coverage::{ @@ -128,6 +129,54 @@ impl<'tcx> FunctionCoverage<'tcx> { self.unreachable_regions.push(region) } + /// Perform some simplifications to make the final coverage mappings + /// slightly smaller. + pub(crate) fn simplify_expressions(&mut self) { + // The set of expressions that either were optimized out entirely, or + // have zero as both of their operands, and will therefore always have + // a value of zero. Other expressions that refer to these as operands + // can have those operands replaced with `Operand::Zero`. + let mut zero_expressions = FxIndexSet::default(); + + // For each expression, perform simplifications based on lower-numbered + // expressions, and then update the set of always-zero expressions if + // necessary. + // (By construction, expressions can only refer to other expressions + // that have lower IDs, so one simplification pass is sufficient.) + for (id, maybe_expression) in self.expressions.iter_enumerated_mut() { + let Some(expression) = maybe_expression else { + // If an expression is missing, it must have been optimized away, + // so any operand that refers to it can be replaced with zero. + zero_expressions.insert(id); + continue; + }; + + // If an operand refers to an expression that is always zero, then + // that operand can be replaced with `Operand::Zero`. + let maybe_set_operand_to_zero = |operand: &mut Operand| match &*operand { + Operand::Expression(id) if zero_expressions.contains(id) => { + *operand = Operand::Zero; + } + _ => (), + }; + maybe_set_operand_to_zero(&mut expression.lhs); + maybe_set_operand_to_zero(&mut expression.rhs); + + // Coverage counter values cannot be negative, so if an expression + // involves subtraction from zero, assume that its RHS must also be zero. + // (Do this after simplifications that could set the LHS to zero.) + if let Expression { lhs: Operand::Zero, op: Op::Subtract, .. } = expression { + expression.rhs = Operand::Zero; + } + + // After the above simplifications, if both operands are zero, then + // we know that this expression is always zero too. + if let Expression { lhs: Operand::Zero, rhs: Operand::Zero, .. } = expression { + zero_expressions.insert(id); + } + } + } + /// Return the source hash, generated from the HIR node structure, and used to indicate whether /// or not the source code structure changed between different compilations. pub fn source_hash(&self) -> u64 { diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 97a99e5105675..d90ac44621d83 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -59,8 +59,10 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) { // Encode coverage mappings and generate function records let mut function_data = Vec::new(); - for (instance, function_coverage) in function_coverage_map { + for (instance, mut function_coverage) in function_coverage_map { debug!("Generate function coverage for {}, {:?}", cx.codegen_unit.name(), instance); + function_coverage.simplify_expressions(); + let mangled_function_name = tcx.symbol_name(instance).name; let source_hash = function_coverage.source_hash(); let is_used = function_coverage.is_used(); diff --git a/tests/coverage-map/status-quo/loops_branches.cov-map b/tests/coverage-map/status-quo/loops_branches.cov-map index ef1aeae97411a..3e442ec01c051 100644 --- a/tests/coverage-map/status-quo/loops_branches.cov-map +++ b/tests/coverage-map/status-quo/loops_branches.cov-map @@ -1,62 +1,58 @@ Function name: ::fmt -Raw bytes (262): 0x[01, 01, 36, 05, 09, 0a, 02, 00, 00, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, d3, 01, d7, 01, 0d, 00, 11, 15, ca, 01, 00, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, c6, 01, 1d, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, be, 01, c2, 01, 00, 00, c6, 01, 1d, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, bb, 01, 11, be, 01, c2, 01, 00, 00, c6, 01, 1d, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, 25, b3, 01, b6, 01, 19, bb, 01, 11, be, 01, c2, 01, 00, 00, c6, 01, 1d, ca, 01, 15, cf, 01, 19, d3, 01, d7, 01, 0d, 00, 11, 15, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 01, 12, 02, 02, 0e, 00, 0f, 07, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, ca, 01, 03, 0d, 00, 0e, cf, 01, 00, 12, 00, 17, 2b, 01, 10, 00, 14, c6, 01, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, c2, 01, 01, 12, 00, 13, bb, 01, 01, 11, 00, 22, b6, 01, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, af, 01, 01, 05, 00, 06] +Raw bytes (251): 0x[01, 01, 32, 05, 09, 00, 02, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, c3, 01, c7, 01, 0d, 00, 11, 15, ba, 01, 00, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, ba, 01, 15, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, b6, 01, 1d, ba, 01, 15, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, 00, b2, 01, b6, 01, 1d, ba, 01, 15, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, af, 01, 11, 00, b2, 01, b6, 01, 1d, ba, 01, 15, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, 25, a7, 01, aa, 01, 19, af, 01, 11, 00, b2, 01, b6, 01, 1d, ba, 01, 15, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 01, 12, 02, 02, 0e, 00, 0f, 07, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, ba, 01, 03, 0d, 00, 0e, bf, 01, 00, 12, 00, 17, 27, 01, 10, 00, 14, b6, 01, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, b2, 01, 01, 12, 00, 13, af, 01, 01, 11, 00, 22, aa, 01, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, a3, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 -Number of expressions: 54 +Number of expressions: 50 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) -- expression 1 operands: lhs = Expression(2, Sub), rhs = Expression(0, Sub) -- expression 2 operands: lhs = Zero, rhs = Zero -- expression 3 operands: lhs = Expression(51, Add), rhs = Counter(6) -- expression 4 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) -- expression 5 operands: lhs = Counter(3), rhs = Zero -- expression 6 operands: lhs = Counter(4), rhs = Counter(5) -- expression 7 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) -- expression 8 operands: lhs = Counter(3), rhs = Zero -- expression 9 operands: lhs = Counter(4), rhs = Counter(5) -- expression 10 operands: lhs = Expression(50, Sub), rhs = Zero -- expression 11 operands: lhs = Expression(51, Add), rhs = Counter(6) -- expression 12 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) -- expression 13 operands: lhs = Counter(3), rhs = Zero -- expression 14 operands: lhs = Counter(4), rhs = Counter(5) -- expression 15 operands: lhs = Expression(50, Sub), rhs = Counter(5) -- expression 16 operands: lhs = Expression(51, Add), rhs = Counter(6) -- expression 17 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) -- expression 18 operands: lhs = Counter(3), rhs = Zero -- expression 19 operands: lhs = Counter(4), rhs = Counter(5) -- expression 20 operands: lhs = Expression(49, Sub), rhs = Counter(7) -- expression 21 operands: lhs = Expression(50, Sub), rhs = Counter(5) -- expression 22 operands: lhs = Expression(51, Add), rhs = Counter(6) -- expression 23 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) -- expression 24 operands: lhs = Counter(3), rhs = Zero -- expression 25 operands: lhs = Counter(4), rhs = Counter(5) -- expression 26 operands: lhs = Expression(47, Sub), rhs = Expression(48, Sub) -- expression 27 operands: lhs = Zero, rhs = Zero -- expression 28 operands: lhs = Expression(49, Sub), rhs = Counter(7) -- expression 29 operands: lhs = Expression(50, Sub), rhs = Counter(5) -- expression 30 operands: lhs = Expression(51, Add), rhs = Counter(6) -- expression 31 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) -- expression 32 operands: lhs = Counter(3), rhs = Zero -- expression 33 operands: lhs = Counter(4), rhs = Counter(5) -- expression 34 operands: lhs = Expression(46, Add), rhs = Counter(4) -- expression 35 operands: lhs = Expression(47, Sub), rhs = Expression(48, Sub) -- expression 36 operands: lhs = Zero, rhs = Zero -- expression 37 operands: lhs = Expression(49, Sub), rhs = Counter(7) -- expression 38 operands: lhs = Expression(50, Sub), rhs = Counter(5) -- expression 39 operands: lhs = Expression(51, Add), rhs = Counter(6) -- expression 40 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) -- expression 41 operands: lhs = Counter(3), rhs = Zero -- expression 42 operands: lhs = Counter(4), rhs = Counter(5) -- expression 43 operands: lhs = Counter(9), rhs = Expression(44, Add) -- expression 44 operands: lhs = Expression(45, Sub), rhs = Counter(6) -- expression 45 operands: lhs = Expression(46, Add), rhs = Counter(4) -- expression 46 operands: lhs = Expression(47, Sub), rhs = Expression(48, Sub) -- expression 47 operands: lhs = Zero, rhs = Zero -- expression 48 operands: lhs = Expression(49, Sub), rhs = Counter(7) -- expression 49 operands: lhs = Expression(50, Sub), rhs = Counter(5) -- expression 50 operands: lhs = Expression(51, Add), rhs = Counter(6) -- expression 51 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) -- expression 52 operands: lhs = Counter(3), rhs = Zero -- expression 53 operands: lhs = Counter(4), rhs = Counter(5) +- expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) +- expression 2 operands: lhs = Expression(47, Add), rhs = Counter(6) +- expression 3 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 4 operands: lhs = Counter(3), rhs = Zero +- expression 5 operands: lhs = Counter(4), rhs = Counter(5) +- expression 6 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 7 operands: lhs = Counter(3), rhs = Zero +- expression 8 operands: lhs = Counter(4), rhs = Counter(5) +- expression 9 operands: lhs = Expression(46, Sub), rhs = Zero +- expression 10 operands: lhs = Expression(47, Add), rhs = Counter(6) +- expression 11 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 12 operands: lhs = Counter(3), rhs = Zero +- expression 13 operands: lhs = Counter(4), rhs = Counter(5) +- expression 14 operands: lhs = Expression(46, Sub), rhs = Counter(5) +- expression 15 operands: lhs = Expression(47, Add), rhs = Counter(6) +- expression 16 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 17 operands: lhs = Counter(3), rhs = Zero +- expression 18 operands: lhs = Counter(4), rhs = Counter(5) +- expression 19 operands: lhs = Expression(45, Sub), rhs = Counter(7) +- expression 20 operands: lhs = Expression(46, Sub), rhs = Counter(5) +- expression 21 operands: lhs = Expression(47, Add), rhs = Counter(6) +- expression 22 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 23 operands: lhs = Counter(3), rhs = Zero +- expression 24 operands: lhs = Counter(4), rhs = Counter(5) +- expression 25 operands: lhs = Zero, rhs = Expression(44, Sub) +- expression 26 operands: lhs = Expression(45, Sub), rhs = Counter(7) +- expression 27 operands: lhs = Expression(46, Sub), rhs = Counter(5) +- expression 28 operands: lhs = Expression(47, Add), rhs = Counter(6) +- expression 29 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 30 operands: lhs = Counter(3), rhs = Zero +- expression 31 operands: lhs = Counter(4), rhs = Counter(5) +- expression 32 operands: lhs = Expression(43, Add), rhs = Counter(4) +- expression 33 operands: lhs = Zero, rhs = Expression(44, Sub) +- expression 34 operands: lhs = Expression(45, Sub), rhs = Counter(7) +- expression 35 operands: lhs = Expression(46, Sub), rhs = Counter(5) +- expression 36 operands: lhs = Expression(47, Add), rhs = Counter(6) +- expression 37 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 38 operands: lhs = Counter(3), rhs = Zero +- expression 39 operands: lhs = Counter(4), rhs = Counter(5) +- expression 40 operands: lhs = Counter(9), rhs = Expression(41, Add) +- expression 41 operands: lhs = Expression(42, Sub), rhs = Counter(6) +- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(4) +- expression 43 operands: lhs = Zero, rhs = Expression(44, Sub) +- expression 44 operands: lhs = Expression(45, Sub), rhs = Counter(7) +- expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(5) +- expression 46 operands: lhs = Expression(47, Add), rhs = Counter(6) +- expression 47 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 48 operands: lhs = Counter(3), rhs = Zero +- expression 49 operands: lhs = Counter(4), rhs = Counter(5) Number of file 0 mappings: 20 - Code(Counter(0)) at (prev + 9, 5) to (start + 1, 16) - Code(Counter(1)) at (prev + 2, 16) to (start + 0, 21) @@ -65,91 +61,87 @@ Number of file 0 mappings: 20 - Code(Expression(0, Sub)) at (prev + 2, 14) to (start + 0, 15) = (c1 - c2) - Code(Expression(1, Add)) at (prev + 1, 13) to (start + 0, 30) - = ((Zero - Zero) + (c1 - c2)) + = (Zero + (c1 - c2)) - Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31) - Code(Zero) at (prev + 1, 16) to (start + 1, 10) -- Code(Expression(50, Sub)) at (prev + 3, 13) to (start + 0, 14) +- Code(Expression(46, Sub)) at (prev + 3, 13) to (start + 0, 14) = (((c3 + Zero) + (c4 + c5)) - c6) -- Code(Expression(51, Add)) at (prev + 0, 18) to (start + 0, 23) +- Code(Expression(47, Add)) at (prev + 0, 18) to (start + 0, 23) = ((c3 + Zero) + (c4 + c5)) -- Code(Expression(10, Add)) at (prev + 1, 16) to (start + 0, 20) +- Code(Expression(9, Add)) at (prev + 1, 16) to (start + 0, 20) = ((((c3 + Zero) + (c4 + c5)) - c6) + Zero) -- Code(Expression(49, Sub)) at (prev + 1, 20) to (start + 0, 25) +- Code(Expression(45, Sub)) at (prev + 1, 20) to (start + 0, 25) = ((((c3 + Zero) + (c4 + c5)) - c6) - c5) - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) -- Code(Expression(48, Sub)) at (prev + 1, 18) to (start + 0, 19) +- Code(Expression(44, Sub)) at (prev + 1, 18) to (start + 0, 19) = (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7) -- Code(Expression(46, Add)) at (prev + 1, 17) to (start + 0, 34) - = ((Zero - Zero) + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) -- Code(Expression(45, Sub)) at (prev + 0, 34) to (start + 0, 35) - = (((Zero - Zero) + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) - c4) +- Code(Expression(43, Add)) at (prev + 1, 17) to (start + 0, 34) + = (Zero + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) +- Code(Expression(42, Sub)) at (prev + 0, 34) to (start + 0, 35) + = ((Zero + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) - c4) - Code(Zero) at (prev + 1, 20) to (start + 1, 14) - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) -- Code(Expression(43, Add)) at (prev + 1, 5) to (start + 0, 6) - = (c9 + ((((Zero - Zero) + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) - c4) + c6)) +- Code(Expression(40, Add)) at (prev + 1, 5) to (start + 0, 6) + = (c9 + (((Zero + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) - c4) + c6)) Function name: ::fmt -Raw bytes (266): 0x[01, 01, 38, 01, 05, 02, 09, 0e, 12, 00, 00, 02, 09, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, d7, 01, db, 01, 05, 0d, 11, 15, ce, 01, 00, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, ca, 01, 1d, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, c2, 01, c6, 01, 00, 00, ca, 01, 1d, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, bf, 01, 15, c2, 01, c6, 01, 00, 00, ca, 01, 1d, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, ba, 01, df, 01, bf, 01, 15, c2, 01, c6, 01, 00, 00, ca, 01, 1d, ce, 01, 11, d3, 01, 19, d7, 01, db, 01, 05, 0d, 11, 15, 19, 25, 14, 01, 23, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 12, 01, 0e, 00, 0f, 0b, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, ce, 01, 02, 0d, 00, 0e, d3, 01, 00, 12, 00, 17, 33, 01, 10, 00, 15, 00, 00, 16, 01, 0e, ca, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, c6, 01, 01, 12, 00, 13, bf, 01, 01, 11, 00, 22, ba, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, b7, 01, 01, 05, 00, 06] +Raw bytes (255): 0x[01, 01, 34, 01, 05, 02, 09, 00, 0e, 02, 09, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, c7, 01, cb, 01, 05, 0d, 11, 15, be, 01, 00, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, be, 01, 11, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, ba, 01, 1d, be, 01, 11, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, 00, b6, 01, ba, 01, 1d, be, 01, 11, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, b3, 01, 15, 00, b6, 01, ba, 01, 1d, be, 01, 11, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, ae, 01, cf, 01, b3, 01, 15, 00, b6, 01, ba, 01, 1d, be, 01, 11, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, 19, 25, 14, 01, 23, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 0e, 01, 0e, 00, 0f, 0b, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, be, 01, 02, 0d, 00, 0e, c3, 01, 00, 12, 00, 17, 2f, 01, 10, 00, 15, 00, 00, 16, 01, 0e, ba, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, b6, 01, 01, 12, 00, 13, b3, 01, 01, 11, 00, 22, ae, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, ab, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 -Number of expressions: 56 +Number of expressions: 52 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Expression(0, Sub), rhs = Counter(2) -- expression 2 operands: lhs = Expression(3, Sub), rhs = Expression(4, Sub) -- expression 3 operands: lhs = Zero, rhs = Zero -- expression 4 operands: lhs = Expression(0, Sub), rhs = Counter(2) -- expression 5 operands: lhs = Expression(52, Add), rhs = Counter(6) -- expression 6 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) -- expression 7 operands: lhs = Counter(1), rhs = Counter(3) -- expression 8 operands: lhs = Counter(4), rhs = Counter(5) -- expression 9 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) -- expression 10 operands: lhs = Counter(1), rhs = Counter(3) -- expression 11 operands: lhs = Counter(4), rhs = Counter(5) -- expression 12 operands: lhs = Expression(51, Sub), rhs = Zero -- expression 13 operands: lhs = Expression(52, Add), rhs = Counter(6) -- expression 14 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) -- expression 15 operands: lhs = Counter(1), rhs = Counter(3) -- expression 16 operands: lhs = Counter(4), rhs = Counter(5) -- expression 17 operands: lhs = Expression(51, Sub), rhs = Counter(4) -- expression 18 operands: lhs = Expression(52, Add), rhs = Counter(6) -- expression 19 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) -- expression 20 operands: lhs = Counter(1), rhs = Counter(3) -- expression 21 operands: lhs = Counter(4), rhs = Counter(5) -- expression 22 operands: lhs = Expression(50, Sub), rhs = Counter(7) -- expression 23 operands: lhs = Expression(51, Sub), rhs = Counter(4) -- expression 24 operands: lhs = Expression(52, Add), rhs = Counter(6) -- expression 25 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) -- expression 26 operands: lhs = Counter(1), rhs = Counter(3) -- expression 27 operands: lhs = Counter(4), rhs = Counter(5) -- expression 28 operands: lhs = Expression(48, Sub), rhs = Expression(49, Sub) -- expression 29 operands: lhs = Zero, rhs = Zero -- expression 30 operands: lhs = Expression(50, Sub), rhs = Counter(7) -- expression 31 operands: lhs = Expression(51, Sub), rhs = Counter(4) -- expression 32 operands: lhs = Expression(52, Add), rhs = Counter(6) -- expression 33 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) -- expression 34 operands: lhs = Counter(1), rhs = Counter(3) -- expression 35 operands: lhs = Counter(4), rhs = Counter(5) -- expression 36 operands: lhs = Expression(47, Add), rhs = Counter(5) -- expression 37 operands: lhs = Expression(48, Sub), rhs = Expression(49, Sub) -- expression 38 operands: lhs = Zero, rhs = Zero -- expression 39 operands: lhs = Expression(50, Sub), rhs = Counter(7) -- expression 40 operands: lhs = Expression(51, Sub), rhs = Counter(4) -- expression 41 operands: lhs = Expression(52, Add), rhs = Counter(6) -- expression 42 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) -- expression 43 operands: lhs = Counter(1), rhs = Counter(3) -- expression 44 operands: lhs = Counter(4), rhs = Counter(5) -- expression 45 operands: lhs = Expression(46, Sub), rhs = Expression(55, Add) -- expression 46 operands: lhs = Expression(47, Add), rhs = Counter(5) -- expression 47 operands: lhs = Expression(48, Sub), rhs = Expression(49, Sub) -- expression 48 operands: lhs = Zero, rhs = Zero -- expression 49 operands: lhs = Expression(50, Sub), rhs = Counter(7) -- expression 50 operands: lhs = Expression(51, Sub), rhs = Counter(4) -- expression 51 operands: lhs = Expression(52, Add), rhs = Counter(6) -- expression 52 operands: lhs = Expression(53, Add), rhs = Expression(54, Add) -- expression 53 operands: lhs = Counter(1), rhs = Counter(3) -- expression 54 operands: lhs = Counter(4), rhs = Counter(5) -- expression 55 operands: lhs = Counter(6), rhs = Counter(9) +- expression 2 operands: lhs = Zero, rhs = Expression(3, Sub) +- expression 3 operands: lhs = Expression(0, Sub), rhs = Counter(2) +- expression 4 operands: lhs = Expression(48, Add), rhs = Counter(6) +- expression 5 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) +- expression 6 operands: lhs = Counter(1), rhs = Counter(3) +- expression 7 operands: lhs = Counter(4), rhs = Counter(5) +- expression 8 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) +- expression 9 operands: lhs = Counter(1), rhs = Counter(3) +- expression 10 operands: lhs = Counter(4), rhs = Counter(5) +- expression 11 operands: lhs = Expression(47, Sub), rhs = Zero +- expression 12 operands: lhs = Expression(48, Add), rhs = Counter(6) +- expression 13 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) +- expression 14 operands: lhs = Counter(1), rhs = Counter(3) +- expression 15 operands: lhs = Counter(4), rhs = Counter(5) +- expression 16 operands: lhs = Expression(47, Sub), rhs = Counter(4) +- expression 17 operands: lhs = Expression(48, Add), rhs = Counter(6) +- expression 18 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) +- expression 19 operands: lhs = Counter(1), rhs = Counter(3) +- expression 20 operands: lhs = Counter(4), rhs = Counter(5) +- expression 21 operands: lhs = Expression(46, Sub), rhs = Counter(7) +- expression 22 operands: lhs = Expression(47, Sub), rhs = Counter(4) +- expression 23 operands: lhs = Expression(48, Add), rhs = Counter(6) +- expression 24 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) +- expression 25 operands: lhs = Counter(1), rhs = Counter(3) +- expression 26 operands: lhs = Counter(4), rhs = Counter(5) +- expression 27 operands: lhs = Zero, rhs = Expression(45, Sub) +- expression 28 operands: lhs = Expression(46, Sub), rhs = Counter(7) +- expression 29 operands: lhs = Expression(47, Sub), rhs = Counter(4) +- expression 30 operands: lhs = Expression(48, Add), rhs = Counter(6) +- expression 31 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) +- expression 32 operands: lhs = Counter(1), rhs = Counter(3) +- expression 33 operands: lhs = Counter(4), rhs = Counter(5) +- expression 34 operands: lhs = Expression(44, Add), rhs = Counter(5) +- expression 35 operands: lhs = Zero, rhs = Expression(45, Sub) +- expression 36 operands: lhs = Expression(46, Sub), rhs = Counter(7) +- expression 37 operands: lhs = Expression(47, Sub), rhs = Counter(4) +- expression 38 operands: lhs = Expression(48, Add), rhs = Counter(6) +- expression 39 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) +- expression 40 operands: lhs = Counter(1), rhs = Counter(3) +- expression 41 operands: lhs = Counter(4), rhs = Counter(5) +- expression 42 operands: lhs = Expression(43, Sub), rhs = Expression(51, Add) +- expression 43 operands: lhs = Expression(44, Add), rhs = Counter(5) +- expression 44 operands: lhs = Zero, rhs = Expression(45, Sub) +- expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(7) +- expression 46 operands: lhs = Expression(47, Sub), rhs = Counter(4) +- expression 47 operands: lhs = Expression(48, Add), rhs = Counter(6) +- expression 48 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) +- expression 49 operands: lhs = Counter(1), rhs = Counter(3) +- expression 50 operands: lhs = Counter(4), rhs = Counter(5) +- expression 51 operands: lhs = Counter(6), rhs = Counter(9) Number of file 0 mappings: 20 - Code(Counter(0)) at (prev + 35, 5) to (start + 1, 17) - Code(Zero) at (prev + 1, 18) to (start + 1, 10) @@ -157,31 +149,31 @@ Number of file 0 mappings: 20 = (c0 - c1) - Code(Zero) at (prev + 1, 23) to (start + 0, 27) - Code(Zero) at (prev + 0, 28) to (start + 0, 30) -- Code(Expression(4, Sub)) at (prev + 1, 14) to (start + 0, 15) +- Code(Expression(3, Sub)) at (prev + 1, 14) to (start + 0, 15) = ((c0 - c1) - c2) - Code(Expression(2, Add)) at (prev + 1, 13) to (start + 0, 30) - = ((Zero - Zero) + ((c0 - c1) - c2)) + = (Zero + ((c0 - c1) - c2)) - Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31) -- Code(Expression(51, Sub)) at (prev + 2, 13) to (start + 0, 14) +- Code(Expression(47, Sub)) at (prev + 2, 13) to (start + 0, 14) = (((c1 + c3) + (c4 + c5)) - c6) -- Code(Expression(52, Add)) at (prev + 0, 18) to (start + 0, 23) +- Code(Expression(48, Add)) at (prev + 0, 18) to (start + 0, 23) = ((c1 + c3) + (c4 + c5)) -- Code(Expression(12, Add)) at (prev + 1, 16) to (start + 0, 21) +- Code(Expression(11, Add)) at (prev + 1, 16) to (start + 0, 21) = ((((c1 + c3) + (c4 + c5)) - c6) + Zero) - Code(Zero) at (prev + 0, 22) to (start + 1, 14) -- Code(Expression(50, Sub)) at (prev + 2, 20) to (start + 0, 25) +- Code(Expression(46, Sub)) at (prev + 2, 20) to (start + 0, 25) = ((((c1 + c3) + (c4 + c5)) - c6) - c4) - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) -- Code(Expression(49, Sub)) at (prev + 1, 18) to (start + 0, 19) +- Code(Expression(45, Sub)) at (prev + 1, 18) to (start + 0, 19) = (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7) -- Code(Expression(47, Add)) at (prev + 1, 17) to (start + 0, 34) - = ((Zero - Zero) + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) -- Code(Expression(46, Sub)) at (prev + 0, 34) to (start + 0, 35) - = (((Zero - Zero) + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) - c5) +- Code(Expression(44, Add)) at (prev + 1, 17) to (start + 0, 34) + = (Zero + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) +- Code(Expression(43, Sub)) at (prev + 0, 34) to (start + 0, 35) + = ((Zero + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) - c5) - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) -- Code(Expression(45, Add)) at (prev + 1, 5) to (start + 0, 6) - = ((((Zero - Zero) + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) - c5) + (c6 + c9)) +- Code(Expression(42, Add)) at (prev + 1, 5) to (start + 0, 6) + = (((Zero + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) - c5) + (c6 + c9)) Function name: loops_branches::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 38, 01, 05, 02] From 5e63f648015a1f96ec07718dfd1885f7eb41b996 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 23 Jul 2023 11:48:31 +1000 Subject: [PATCH 06/11] coverage: Don't bother renumbering expressions on the Rust side The LLVM API that we use to encode coverage mappings already has its own code for removing unused coverage expressions and renumbering the rest. This lets us get rid of our own complex renumbering code, making it easier to refactor our coverage code in other ways. --- .../src/coverageinfo/ffi.rs | 27 +-- .../src/coverageinfo/map_data.rs | 184 +++++------------- compiler/rustc_middle/src/mir/coverage.rs | 10 - .../rustc_middle/src/ty/structural_impls.rs | 1 - 4 files changed, 58 insertions(+), 164 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index fe334b292657d..763186a58bf9f 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -1,4 +1,4 @@ -use rustc_middle::mir::coverage::{CounterId, MappedExpressionIndex}; +use rustc_middle::mir::coverage::{CounterId, ExpressionId, Operand}; /// Must match the layout of `LLVMRustCounterKind`. #[derive(Copy, Clone, Debug)] @@ -39,20 +39,16 @@ impl Counter { } /// Constructs a new `Counter` of kind `Expression`. - pub fn expression(mapped_expression_index: MappedExpressionIndex) -> Self { - Self { kind: CounterKind::Expression, id: mapped_expression_index.into() } + pub(crate) fn expression(expression_id: ExpressionId) -> Self { + Self { kind: CounterKind::Expression, id: expression_id.as_u32() } } - /// Returns true if the `Counter` kind is `Zero`. - pub fn is_zero(&self) -> bool { - matches!(self.kind, CounterKind::Zero) - } - - /// An explicitly-named function to get the ID value, making it more obvious - /// that the stored value is now 0-based. - pub fn zero_based_id(&self) -> u32 { - debug_assert!(!self.is_zero(), "`id` is undefined for CounterKind::Zero"); - self.id + pub(crate) fn from_operand(operand: Operand) -> Self { + match operand { + Operand::Zero => Self::ZERO, + Operand::Counter(id) => Self::counter_value_reference(id), + Operand::Expression(id) => Self::expression(id), + } } } @@ -78,6 +74,11 @@ pub struct CounterExpression { } impl CounterExpression { + /// The dummy expression `(0 - 0)` has a representation of all zeroes, + /// making it marginally more efficient to initialize than `(0 + 0)`. + pub(crate) const DUMMY: Self = + Self { lhs: Counter::ZERO, kind: ExprKind::Subtract, rhs: Counter::ZERO }; + pub fn new(lhs: Counter, kind: ExprKind, rhs: Counter) -> Self { Self { kind, lhs, rhs } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index cabf3cea592f3..fee1fc6f5e9b8 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -1,11 +1,8 @@ use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; use rustc_data_structures::fx::FxIndexSet; -use rustc_index::{IndexSlice, IndexVec}; -use rustc_middle::bug; -use rustc_middle::mir::coverage::{ - CodeRegion, CounterId, ExpressionId, MappedExpressionIndex, Op, Operand, -}; +use rustc_index::IndexVec; +use rustc_middle::mir::coverage::{CodeRegion, CounterId, ExpressionId, Op, Operand}; use rustc_middle::ty::Instance; use rustc_middle::ty::TyCtxt; @@ -195,8 +192,14 @@ impl<'tcx> FunctionCoverage<'tcx> { self.instance ); + let counter_expressions = self.counter_expressions(); + // Expression IDs are indices into `self.expressions`, and on the LLVM + // side they will be treated as indices into `counter_expressions`, so + // the two vectors should correspond 1:1. + assert_eq!(self.expressions.len(), counter_expressions.len()); + let counter_regions = self.counter_regions(); - let (counter_expressions, expression_regions) = self.expressions_with_regions(); + let expression_regions = self.expression_regions(); let unreachable_regions = self.unreachable_regions(); let counter_regions = @@ -212,146 +215,47 @@ impl<'tcx> FunctionCoverage<'tcx> { }) } - fn expressions_with_regions( - &self, - ) -> (Vec, impl Iterator) { - let mut counter_expressions = Vec::with_capacity(self.expressions.len()); - let mut expression_regions = Vec::with_capacity(self.expressions.len()); - let mut new_indexes = IndexVec::from_elem_n(None, self.expressions.len()); - - // This closure converts any `Expression` operand (`lhs` or `rhs` of the `Op::Add` or - // `Op::Subtract` operation) into its native `llvm::coverage::Counter::CounterKind` type - // and value. - // - // Expressions will be returned from this function in a sequential vector (array) of - // `CounterExpression`, so the expression IDs must be mapped from their original, - // potentially sparse set of indexes. - // - // An `Expression` as an operand will have already been encountered as an `Expression` with - // operands, so its new_index will already have been generated (as a 1-up index value). - // (If an `Expression` as an operand does not have a corresponding new_index, it was - // probably optimized out, after the expression was injected into the MIR, so it will - // get a `CounterKind::Zero` instead.) - // - // In other words, an `Expression`s at any given index can include other expressions as - // operands, but expression operands can only come from the subset of expressions having - // `expression_index`s lower than the referencing `Expression`. Therefore, it is - // reasonable to look up the new index of an expression operand while the `new_indexes` - // vector is only complete up to the current `ExpressionIndex`. - type NewIndexes = IndexSlice>; - let id_to_counter = |new_indexes: &NewIndexes, operand: Operand| match operand { - Operand::Zero => Some(Counter::ZERO), - Operand::Counter(id) => Some(Counter::counter_value_reference(id)), - Operand::Expression(id) => { - self.expressions - .get(id) - .expect("expression id is out of range") - .as_ref() - // If an expression was optimized out, assume it would have produced a count - // of zero. This ensures that expressions dependent on optimized-out - // expressions are still valid. - .map_or(Some(Counter::ZERO), |_| new_indexes[id].map(Counter::expression)) - } - }; - - for (original_index, expression) in - self.expressions.iter_enumerated().filter_map(|(original_index, entry)| { - // Option::map() will return None to filter out missing expressions. This may happen - // if, for example, a MIR-instrumented expression is removed during an optimization. - entry.as_ref().map(|expression| (original_index, expression)) - }) - { - let optional_region = &expression.region; - let Expression { lhs, op, rhs, .. } = *expression; + /// Convert this function's coverage expression data into a form that can be + /// passed through FFI to LLVM. + fn counter_expressions(&self) -> Vec { + // We know that LLVM will optimize out any unused expressions before + // producing the final coverage map, so there's no need to do the same + // thing on the Rust side unless we're confident we can do much better. + // (See `CounterExpressionsMinimizer` in `CoverageMappingWriter.cpp`.) - if let Some(Some((lhs_counter, mut rhs_counter))) = id_to_counter(&new_indexes, lhs) - .map(|lhs_counter| { - id_to_counter(&new_indexes, rhs).map(|rhs_counter| (lhs_counter, rhs_counter)) - }) - { - if lhs_counter.is_zero() && op.is_subtract() { - // The left side of a subtraction was probably optimized out. As an example, - // a branch condition might be evaluated as a constant expression, and the - // branch could be removed, dropping unused counters in the process. - // - // Since counters are unsigned, we must assume the result of the expression - // can be no more and no less than zero. An expression known to evaluate to zero - // does not need to be added to the coverage map. - // - // Coverage test `loops_branches.rs` includes multiple variations of branches - // based on constant conditional (literal `true` or `false`), and demonstrates - // that the expected counts are still correct. - debug!( - "Expression subtracts from zero (assume unreachable): \ - original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}", - original_index, lhs, op, rhs, optional_region, - ); - rhs_counter = Counter::ZERO; + self.expressions + .iter() + .map(|expression| match expression { + None => { + // This expression ID was allocated, but we never saw the + // actual expression, so it must have been optimized out. + // Replace it with a dummy expression, and let LLVM take + // care of omitting it from the expression list. + CounterExpression::DUMMY } - debug_assert!( - lhs_counter.is_zero() - // Note: with `as usize` the ID _could_ overflow/wrap if `usize = u16` - || ((lhs_counter.zero_based_id() as usize) - <= usize::max(self.counters.len(), self.expressions.len())), - "lhs id={} > both counters.len()={} and expressions.len()={} - ({:?} {:?} {:?})", - lhs_counter.zero_based_id(), - self.counters.len(), - self.expressions.len(), - lhs_counter, - op, - rhs_counter, - ); - - debug_assert!( - rhs_counter.is_zero() - // Note: with `as usize` the ID _could_ overflow/wrap if `usize = u16` - || ((rhs_counter.zero_based_id() as usize) - <= usize::max(self.counters.len(), self.expressions.len())), - "rhs id={} > both counters.len()={} and expressions.len()={} - ({:?} {:?} {:?})", - rhs_counter.zero_based_id(), - self.counters.len(), - self.expressions.len(), - lhs_counter, - op, - rhs_counter, - ); - - // Both operands exist. `Expression` operands exist in `self.expressions` and have - // been assigned a `new_index`. - let mapped_expression_index = - MappedExpressionIndex::from(counter_expressions.len()); - let expression = CounterExpression::new( - lhs_counter, + &Some(Expression { lhs, op, rhs, .. }) => CounterExpression::new( + Counter::from_operand(lhs), match op { Op::Add => ExprKind::Add, Op::Subtract => ExprKind::Subtract, }, - rhs_counter, - ); - debug!( - "Adding expression {:?} = {:?}, region: {:?}", - mapped_expression_index, expression, optional_region - ); - counter_expressions.push(expression); - new_indexes[original_index] = Some(mapped_expression_index); - if let Some(region) = optional_region { - expression_regions.push((Counter::expression(mapped_expression_index), region)); - } - } else { - bug!( - "expression has one or more missing operands \ - original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}", - original_index, - lhs, - op, - rhs, - optional_region, - ); - } - } - (counter_expressions, expression_regions.into_iter()) + Counter::from_operand(rhs), + ), + }) + .collect::>() + } + + fn expression_regions(&self) -> Vec<(Counter, &CodeRegion)> { + // Find all of the expression IDs that weren't optimized out AND have + // an attached code region, and return the corresponding mapping as a + // counter/region pair. + self.expressions + .iter_enumerated() + .filter_map(|(id, expression)| { + let code_region = expression.as_ref()?.region.as_ref()?; + Some((Counter::expression(id), code_region)) + }) + .collect::>() } fn unreachable_regions(&self) -> impl Iterator { diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 1efb54bdb0872..9ef6739229118 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -45,16 +45,6 @@ impl ExpressionId { } } -rustc_index::newtype_index! { - /// MappedExpressionIndex values ascend from zero, and are recalculated indexes based on their - /// array position in the LLVM coverage map "Expressions" array, which is assembled during the - /// "mapgen" process. They cannot be computed algorithmically, from the other `newtype_index`s. - #[derive(HashStable)] - #[max = 0xFFFF_FFFF] - #[debug_format = "MappedExpressionIndex({})"] - pub struct MappedExpressionIndex {} -} - /// Operand of a coverage-counter expression. /// /// Operands can be a constant zero value, an actual coverage counter, or another diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index f979ddd00fa01..7e93a236308b8 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -469,7 +469,6 @@ TrivialTypeTraversalAndLiftImpls! { ::rustc_target::spec::abi::Abi, crate::mir::coverage::CounterId, crate::mir::coverage::ExpressionId, - crate::mir::coverage::MappedExpressionIndex, crate::mir::Local, crate::mir::Promoted, crate::traits::Reveal, From bae94ee311f6faf9509b25b26ef30aac5f0d5f82 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Wed, 23 Aug 2023 13:41:49 +0200 Subject: [PATCH 07/11] Generalize Coverage Expression simplification This extends the current simplification code to not only replace operands by `Zero`, but also to remove trivial `Counter + Zero` expressions and replace those with just `Counter`. Currently this simplification is very simplistic, and does not handle more complex nested expressions such as `(A + B) - B` which could in theory be simplified as well. --- .../src/coverageinfo/map_data.rs | 62 +++-- tests/coverage-map/status-quo/async2.cov-map | 36 ++- .../status-quo/conditions.cov-map | 237 ++++++++--------- .../status-quo/drop_trait.cov-map | 8 +- .../coverage-map/status-quo/generics.cov-map | 8 +- .../status-quo/loops_branches.cov-map | 250 ++++++++---------- 6 files changed, 285 insertions(+), 316 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index fee1fc6f5e9b8..942feb97dbbec 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -1,6 +1,6 @@ use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; -use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::fx::FxHashMap; use rustc_index::IndexVec; use rustc_middle::mir::coverage::{CodeRegion, CounterId, ExpressionId, Op, Operand}; use rustc_middle::ty::Instance; @@ -129,14 +129,13 @@ impl<'tcx> FunctionCoverage<'tcx> { /// Perform some simplifications to make the final coverage mappings /// slightly smaller. pub(crate) fn simplify_expressions(&mut self) { - // The set of expressions that either were optimized out entirely, or - // have zero as both of their operands, and will therefore always have - // a value of zero. Other expressions that refer to these as operands - // can have those operands replaced with `Operand::Zero`. - let mut zero_expressions = FxIndexSet::default(); + // The set of expressions that were simplified to either `Zero` or a + // `Counter`. Other expressions that refer to these as operands + // can then also be simplified. + let mut simplified_expressions = FxHashMap::default(); // For each expression, perform simplifications based on lower-numbered - // expressions, and then update the set of always-zero expressions if + // expressions, and then update the map of simplified expressions if // necessary. // (By construction, expressions can only refer to other expressions // that have lower IDs, so one simplification pass is sufficient.) @@ -144,20 +143,22 @@ impl<'tcx> FunctionCoverage<'tcx> { let Some(expression) = maybe_expression else { // If an expression is missing, it must have been optimized away, // so any operand that refers to it can be replaced with zero. - zero_expressions.insert(id); + simplified_expressions.insert(id, Operand::Zero); continue; }; - // If an operand refers to an expression that is always zero, then - // that operand can be replaced with `Operand::Zero`. - let maybe_set_operand_to_zero = |operand: &mut Operand| match &*operand { - Operand::Expression(id) if zero_expressions.contains(id) => { - *operand = Operand::Zero; + // If an operand refers to an expression that has been simplified, then + // replace that operand with the simplified version. + let maybe_simplify_operand = |operand: &mut Operand| { + if let Operand::Expression(id) = &*operand { + if let Some(simplified) = simplified_expressions.get(id) { + *operand = *simplified; + } } - _ => (), }; - maybe_set_operand_to_zero(&mut expression.lhs); - maybe_set_operand_to_zero(&mut expression.rhs); + + maybe_simplify_operand(&mut expression.lhs); + maybe_simplify_operand(&mut expression.rhs); // Coverage counter values cannot be negative, so if an expression // involves subtraction from zero, assume that its RHS must also be zero. @@ -166,12 +167,31 @@ impl<'tcx> FunctionCoverage<'tcx> { expression.rhs = Operand::Zero; } - // After the above simplifications, if both operands are zero, then - // we know that this expression is always zero too. - if let Expression { lhs: Operand::Zero, rhs: Operand::Zero, .. } = expression { - zero_expressions.insert(id); + // After the above simplifications, if the right hand operand is zero, + // we can replace the expression by its left hand side. + if let Expression { lhs, rhs: Operand::Zero, .. } = expression { + simplified_expressions.insert(id, *lhs); + } else + // And the same thing for the left hand side. + if let Expression { lhs: Operand::Zero, rhs, .. } = expression { + simplified_expressions.insert(id, *rhs); + } + } + } + + /// This will further simplify any expression, "inlining" the left hand side operand + /// if the right hand side is `Zero`. This is similar to `simplify_expressions` above, + /// but works for an already referenced expression. + fn simplified_expression(&self, id: ExpressionId) -> Counter { + if let Some(expr) = &self.expressions[id] { + if expr.rhs == Operand::Zero { + return Counter::from_operand(expr.lhs); + } + if expr.lhs == Operand::Zero { + return Counter::from_operand(expr.rhs); } } + Counter::expression(id) } /// Return the source hash, generated from the HIR node structure, and used to indicate whether @@ -253,7 +273,7 @@ impl<'tcx> FunctionCoverage<'tcx> { .iter_enumerated() .filter_map(|(id, expression)| { let code_region = expression.as_ref()?.region.as_ref()?; - Some((Counter::expression(id), code_region)) + Some((self.simplified_expression(id), code_region)) }) .collect::>() } diff --git a/tests/coverage-map/status-quo/async2.cov-map b/tests/coverage-map/status-quo/async2.cov-map index e02db200ba029..773daa4feaaa1 100644 --- a/tests/coverage-map/status-quo/async2.cov-map +++ b/tests/coverage-map/status-quo/async2.cov-map @@ -38,48 +38,44 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 31, 36) to (start + 2, 2) Function name: async2::executor::block_on:: -Raw bytes (44): 0x[01, 01, 05, 0b, 05, 01, 05, 01, 05, 02, 00, 02, 00, 06, 01, 33, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 0f, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 13, 02, 05, 00, 06] +Raw bytes (40): 0x[01, 01, 03, 0b, 05, 01, 05, 01, 05, 06, 01, 33, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 02, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 02, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 -Number of expressions: 5 +Number of expressions: 3 - expression 0 operands: lhs = Expression(2, Add), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(1) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) -- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero -- expression 4 operands: lhs = Expression(0, Sub), rhs = Zero Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 51, 5) to (start + 10, 54) - Code(Expression(0, Sub)) at (prev + 13, 32) to (start + 0, 35) = ((c0 + c1) - c1) - Code(Expression(2, Add)) at (prev + 0, 39) to (start + 0, 73) = (c0 + c1) -- Code(Expression(3, Add)) at (prev + 1, 23) to (start + 0, 26) - = (((c0 + c1) - c1) + Zero) +- Code(Expression(0, Sub)) at (prev + 1, 23) to (start + 0, 26) + = ((c0 + c1) - c1) - Code(Counter(1)) at (prev + 1, 14) to (start + 0, 15) -- Code(Expression(4, Add)) at (prev + 2, 5) to (start + 0, 6) - = (((c0 + c1) - c1) + Zero) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) + = ((c0 + c1) - c1) Function name: async2::executor::block_on:: -Raw bytes (44): 0x[01, 01, 05, 0b, 05, 01, 05, 01, 05, 02, 00, 02, 00, 06, 01, 33, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 0f, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 13, 02, 05, 00, 06] +Raw bytes (40): 0x[01, 01, 03, 0b, 05, 01, 05, 01, 05, 06, 01, 33, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 02, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 02, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 -Number of expressions: 5 +Number of expressions: 3 - expression 0 operands: lhs = Expression(2, Add), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(1) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) -- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero -- expression 4 operands: lhs = Expression(0, Sub), rhs = Zero Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 51, 5) to (start + 10, 54) - Code(Expression(0, Sub)) at (prev + 13, 32) to (start + 0, 35) = ((c0 + c1) - c1) - Code(Expression(2, Add)) at (prev + 0, 39) to (start + 0, 73) = (c0 + c1) -- Code(Expression(3, Add)) at (prev + 1, 23) to (start + 0, 26) - = (((c0 + c1) - c1) + Zero) +- Code(Expression(0, Sub)) at (prev + 1, 23) to (start + 0, 26) + = ((c0 + c1) - c1) - Code(Counter(1)) at (prev + 1, 14) to (start + 0, 15) -- Code(Expression(4, Add)) at (prev + 2, 5) to (start + 0, 6) - = (((c0 + c1) - c1) + Zero) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) + = ((c0 + c1) - c1) Function name: async2::executor::block_on::VTABLE::{closure#0} Raw bytes (9): 0x[01, 01, 00, 01, 01, 37, 11, 00, 33] @@ -122,15 +118,13 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 35, 1) to (start + 7, 2) Function name: async2::non_async_func -Raw bytes (26): 0x[01, 01, 01, 05, 00, 04, 01, 09, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 03, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 09, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 05, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(1), rhs = Zero +Number of expressions: 0 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 9, 1) to (start + 3, 9) - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) -- Code(Expression(0, Add)) at (prev + 1, 1) to (start + 0, 2) - = (c1 + Zero) +- Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) diff --git a/tests/coverage-map/status-quo/conditions.cov-map b/tests/coverage-map/status-quo/conditions.cov-map index 2c2ece508b0dc..844a625cf4723 100644 --- a/tests/coverage-map/status-quo/conditions.cov-map +++ b/tests/coverage-map/status-quo/conditions.cov-map @@ -1,186 +1,163 @@ Function name: conditions::main -Raw bytes (564): 0x[01, 01, 4f, 09, 1b, 2d, 31, 05, 00, bb, 02, 09, 05, 00, 0d, 39, 2d, 31, b6, 02, 0d, bb, 02, 09, 05, 00, 03, 00, 35, 00, 53, 3d, 35, 00, 4e, 29, 53, 3d, 35, 00, 4a, 51, 4e, 29, 53, 3d, 35, 00, 45, 49, 3d, 5f, 45, 49, 55, 00, 87, 01, 59, 55, 00, 82, 01, 25, 87, 01, 59, 55, 00, 7e, 79, 82, 01, 25, 87, 01, 59, 55, 00, 5d, 61, 93, 01, 00, 59, 97, 01, 5d, 61, 6d, 8f, 02, 71, 75, 65, 00, c7, 01, 6d, 65, 00, c2, 01, 21, c7, 01, 6d, 65, 00, be, 01, 7d, c2, 01, 21, c7, 01, 6d, 65, 00, 71, 75, 11, 9f, 02, 15, 19, 8b, 02, 00, 6d, 8f, 02, 71, 75, 8b, 02, 11, 6d, 8f, 02, 71, 75, 86, 02, 1d, 8b, 02, 11, 6d, 8f, 02, 71, 75, 82, 02, 89, 01, 86, 02, 1d, 8b, 02, 11, 6d, 8f, 02, 71, 75, 15, 19, 9b, 02, a3, 02, 11, 9f, 02, 15, 19, a7, 02, b2, 02, ab, 02, af, 02, 1d, 21, 25, 29, b6, 02, 0d, bb, 02, 09, 05, 00, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 03, 09, 00, 0a, bb, 02, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, b6, 02, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 16, 00, 1d, 00, 2a, 41, 00, 2e, 00, 3c, 2d, 00, 3d, 02, 0a, 31, 02, 0a, 00, 0b, 1b, 01, 09, 01, 12, b2, 02, 03, 09, 00, 0f, 2b, 03, 09, 01, 0c, 35, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 53, 02, 08, 00, 15, 3d, 00, 16, 02, 06, 4e, 02, 0f, 00, 1c, 4a, 01, 0c, 00, 19, 46, 00, 1d, 00, 2a, 69, 00, 2e, 00, 3c, 45, 00, 3d, 02, 0a, 49, 02, 0a, 00, 0b, 5f, 01, 09, 00, 17, 29, 02, 09, 00, 0f, 5b, 03, 08, 00, 0c, 4d, 01, 0d, 01, 10, 55, 01, 11, 02, 0a, 00, 02, 0a, 00, 0b, 87, 01, 02, 0c, 00, 19, 59, 00, 1a, 02, 0a, 82, 01, 03, 11, 00, 1e, 7e, 01, 10, 00, 1d, 7a, 00, 21, 00, 2e, 81, 01, 00, 32, 00, 40, 5d, 00, 41, 02, 0e, 61, 02, 0e, 00, 0f, 97, 01, 01, 0d, 00, 1b, 25, 02, 0d, 00, 13, 00, 02, 06, 00, 07, 8f, 01, 03, 09, 01, 0c, 65, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 8b, 02, 02, 09, 00, 0a, c7, 01, 00, 10, 00, 1d, 6d, 00, 1e, 02, 06, c2, 01, 02, 0f, 00, 1c, be, 01, 01, 0c, 00, 19, ba, 01, 00, 1d, 00, 2a, 85, 01, 00, 2e, 00, 3c, 71, 00, 3d, 02, 0a, 75, 02, 0a, 00, 0b, 8f, 02, 01, 09, 00, 17, 21, 02, 0d, 02, 0f, 9b, 02, 05, 09, 00, 0a, d7, 01, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, 86, 02, 02, 0f, 00, 1c, 82, 02, 01, 0c, 00, 19, fe, 01, 00, 1d, 00, 2a, 8d, 01, 00, 2e, 00, 3c, 15, 00, 3d, 02, 0a, 19, 02, 0a, 00, 0b, 9f, 02, 01, 09, 00, 17, 1d, 02, 09, 00, 0f, 97, 02, 02, 01, 00, 02] +Raw bytes (503): 0x[01, 01, 3c, 09, 13, 2d, 31, 05, 09, 0d, 39, 2d, 31, ee, 01, 0d, 05, 09, 35, 3d, 32, 29, 35, 3d, 2e, 51, 32, 29, 35, 3d, 45, 49, 3d, 3f, 45, 49, 55, 59, 56, 25, 55, 59, 52, 79, 56, 25, 55, 59, 5d, 61, 59, 63, 5d, 61, 6d, c7, 01, 71, 75, 65, 6d, 82, 01, 21, 65, 6d, 7e, 7d, 82, 01, 21, 65, 6d, 71, 75, 11, d7, 01, 15, 19, 6d, c7, 01, 71, 75, c3, 01, 11, 6d, c7, 01, 71, 75, be, 01, 1d, c3, 01, 11, 6d, c7, 01, 71, 75, ba, 01, 89, 01, be, 01, 1d, c3, 01, 11, 6d, c7, 01, 71, 75, 15, 19, d3, 01, db, 01, 11, d7, 01, 15, 19, df, 01, ea, 01, e3, 01, e7, 01, 1d, 21, 25, 29, ee, 01, 0d, 05, 09, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 03, 09, 00, 0a, 05, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, ee, 01, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 0e, 00, 1d, 00, 2a, 41, 00, 2e, 00, 3c, 2d, 00, 3d, 02, 0a, 31, 02, 0a, 00, 0b, 13, 01, 09, 01, 12, ea, 01, 03, 09, 00, 0f, 03, 03, 09, 01, 0c, 35, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 35, 02, 08, 00, 15, 3d, 00, 16, 02, 06, 32, 02, 0f, 00, 1c, 2e, 01, 0c, 00, 19, 2a, 00, 1d, 00, 2a, 69, 00, 2e, 00, 3c, 45, 00, 3d, 02, 0a, 49, 02, 0a, 00, 0b, 3f, 01, 09, 00, 17, 29, 02, 09, 00, 0f, 3b, 03, 08, 00, 0c, 4d, 01, 0d, 01, 10, 55, 01, 11, 02, 0a, 00, 02, 0a, 00, 0b, 55, 02, 0c, 00, 19, 59, 00, 1a, 02, 0a, 56, 03, 11, 00, 1e, 52, 01, 10, 00, 1d, 4e, 00, 21, 00, 2e, 81, 01, 00, 32, 00, 40, 5d, 00, 41, 02, 0e, 61, 02, 0e, 00, 0f, 63, 01, 0d, 00, 1b, 25, 02, 0d, 00, 13, 00, 02, 06, 00, 07, 5f, 03, 09, 01, 0c, 65, 01, 0d, 02, 06, 00, 02, 06, 00, 07, c3, 01, 02, 09, 00, 0a, 65, 00, 10, 00, 1d, 6d, 00, 1e, 02, 06, 82, 01, 02, 0f, 00, 1c, 7e, 01, 0c, 00, 19, 7a, 00, 1d, 00, 2a, 85, 01, 00, 2e, 00, 3c, 71, 00, 3d, 02, 0a, 75, 02, 0a, 00, 0b, c7, 01, 01, 09, 00, 17, 21, 02, 0d, 02, 0f, d3, 01, 05, 09, 00, 0a, c3, 01, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, be, 01, 02, 0f, 00, 1c, ba, 01, 01, 0c, 00, 19, b6, 01, 00, 1d, 00, 2a, 8d, 01, 00, 2e, 00, 3c, 15, 00, 3d, 02, 0a, 19, 02, 0a, 00, 0b, d7, 01, 01, 09, 00, 17, 1d, 02, 09, 00, 0f, cf, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 79 -- expression 0 operands: lhs = Counter(2), rhs = Expression(6, Add) +Number of expressions: 60 +- expression 0 operands: lhs = Counter(2), rhs = Expression(4, Add) - expression 1 operands: lhs = Counter(11), rhs = Counter(12) -- expression 2 operands: lhs = Counter(1), rhs = Zero -- expression 3 operands: lhs = Expression(78, Add), rhs = Counter(2) -- expression 4 operands: lhs = Counter(1), rhs = Zero -- expression 5 operands: lhs = Counter(3), rhs = Counter(14) -- expression 6 operands: lhs = Counter(11), rhs = Counter(12) -- expression 7 operands: lhs = Expression(77, Sub), rhs = Counter(3) -- expression 8 operands: lhs = Expression(78, Add), rhs = Counter(2) -- expression 9 operands: lhs = Counter(1), rhs = Zero -- expression 10 operands: lhs = Expression(0, Add), rhs = Zero -- expression 11 operands: lhs = Counter(13), rhs = Zero -- expression 12 operands: lhs = Expression(20, Add), rhs = Counter(15) -- expression 13 operands: lhs = Counter(13), rhs = Zero -- expression 14 operands: lhs = Expression(19, Sub), rhs = Counter(10) -- expression 15 operands: lhs = Expression(20, Add), rhs = Counter(15) -- expression 16 operands: lhs = Counter(13), rhs = Zero -- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(20) -- expression 18 operands: lhs = Expression(19, Sub), rhs = Counter(10) -- expression 19 operands: lhs = Expression(20, Add), rhs = Counter(15) -- expression 20 operands: lhs = Counter(13), rhs = Zero -- expression 21 operands: lhs = Counter(17), rhs = Counter(18) -- expression 22 operands: lhs = Counter(15), rhs = Expression(23, Add) -- expression 23 operands: lhs = Counter(17), rhs = Counter(18) -- expression 24 operands: lhs = Counter(21), rhs = Zero -- expression 25 operands: lhs = Expression(33, Add), rhs = Counter(22) -- expression 26 operands: lhs = Counter(21), rhs = Zero -- expression 27 operands: lhs = Expression(32, Sub), rhs = Counter(9) -- expression 28 operands: lhs = Expression(33, Add), rhs = Counter(22) -- expression 29 operands: lhs = Counter(21), rhs = Zero -- expression 30 operands: lhs = Expression(31, Sub), rhs = Counter(30) -- expression 31 operands: lhs = Expression(32, Sub), rhs = Counter(9) -- expression 32 operands: lhs = Expression(33, Add), rhs = Counter(22) -- expression 33 operands: lhs = Counter(21), rhs = Zero -- expression 34 operands: lhs = Counter(23), rhs = Counter(24) -- expression 35 operands: lhs = Expression(36, Add), rhs = Zero -- expression 36 operands: lhs = Counter(22), rhs = Expression(37, Add) -- expression 37 operands: lhs = Counter(23), rhs = Counter(24) -- expression 38 operands: lhs = Counter(27), rhs = Expression(67, Add) -- expression 39 operands: lhs = Counter(28), rhs = Counter(29) -- expression 40 operands: lhs = Counter(25), rhs = Zero -- expression 41 operands: lhs = Expression(49, Add), rhs = Counter(27) -- expression 42 operands: lhs = Counter(25), rhs = Zero -- expression 43 operands: lhs = Expression(48, Sub), rhs = Counter(8) -- expression 44 operands: lhs = Expression(49, Add), rhs = Counter(27) -- expression 45 operands: lhs = Counter(25), rhs = Zero -- expression 46 operands: lhs = Expression(47, Sub), rhs = Counter(31) -- expression 47 operands: lhs = Expression(48, Sub), rhs = Counter(8) -- expression 48 operands: lhs = Expression(49, Add), rhs = Counter(27) -- expression 49 operands: lhs = Counter(25), rhs = Zero -- expression 50 operands: lhs = Counter(28), rhs = Counter(29) -- expression 51 operands: lhs = Counter(4), rhs = Expression(71, Add) -- expression 52 operands: lhs = Counter(5), rhs = Counter(6) -- expression 53 operands: lhs = Expression(66, Add), rhs = Zero -- expression 54 operands: lhs = Counter(27), rhs = Expression(67, Add) -- expression 55 operands: lhs = Counter(28), rhs = Counter(29) -- expression 56 operands: lhs = Expression(66, Add), rhs = Counter(4) -- expression 57 operands: lhs = Counter(27), rhs = Expression(67, Add) -- expression 58 operands: lhs = Counter(28), rhs = Counter(29) -- expression 59 operands: lhs = Expression(65, Sub), rhs = Counter(7) -- expression 60 operands: lhs = Expression(66, Add), rhs = Counter(4) -- expression 61 operands: lhs = Counter(27), rhs = Expression(67, Add) -- expression 62 operands: lhs = Counter(28), rhs = Counter(29) -- expression 63 operands: lhs = Expression(64, Sub), rhs = Counter(34) -- expression 64 operands: lhs = Expression(65, Sub), rhs = Counter(7) -- expression 65 operands: lhs = Expression(66, Add), rhs = Counter(4) -- expression 66 operands: lhs = Counter(27), rhs = Expression(67, Add) -- expression 67 operands: lhs = Counter(28), rhs = Counter(29) -- expression 68 operands: lhs = Counter(5), rhs = Counter(6) -- expression 69 operands: lhs = Expression(70, Add), rhs = Expression(72, Add) -- expression 70 operands: lhs = Counter(4), rhs = Expression(71, Add) -- expression 71 operands: lhs = Counter(5), rhs = Counter(6) -- expression 72 operands: lhs = Expression(73, Add), rhs = Expression(76, Sub) -- expression 73 operands: lhs = Expression(74, Add), rhs = Expression(75, Add) -- expression 74 operands: lhs = Counter(7), rhs = Counter(8) -- expression 75 operands: lhs = Counter(9), rhs = Counter(10) -- expression 76 operands: lhs = Expression(77, Sub), rhs = Counter(3) -- expression 77 operands: lhs = Expression(78, Add), rhs = Counter(2) -- expression 78 operands: lhs = Counter(1), rhs = Zero +- expression 2 operands: lhs = Counter(1), rhs = Counter(2) +- expression 3 operands: lhs = Counter(3), rhs = Counter(14) +- expression 4 operands: lhs = Counter(11), rhs = Counter(12) +- expression 5 operands: lhs = Expression(59, Sub), rhs = Counter(3) +- expression 6 operands: lhs = Counter(1), rhs = Counter(2) +- expression 7 operands: lhs = Counter(13), rhs = Counter(15) +- expression 8 operands: lhs = Expression(12, Sub), rhs = Counter(10) +- expression 9 operands: lhs = Counter(13), rhs = Counter(15) +- expression 10 operands: lhs = Expression(11, Sub), rhs = Counter(20) +- expression 11 operands: lhs = Expression(12, Sub), rhs = Counter(10) +- expression 12 operands: lhs = Counter(13), rhs = Counter(15) +- expression 13 operands: lhs = Counter(17), rhs = Counter(18) +- expression 14 operands: lhs = Counter(15), rhs = Expression(15, Add) +- expression 15 operands: lhs = Counter(17), rhs = Counter(18) +- expression 16 operands: lhs = Counter(21), rhs = Counter(22) +- expression 17 operands: lhs = Expression(21, Sub), rhs = Counter(9) +- expression 18 operands: lhs = Counter(21), rhs = Counter(22) +- expression 19 operands: lhs = Expression(20, Sub), rhs = Counter(30) +- expression 20 operands: lhs = Expression(21, Sub), rhs = Counter(9) +- expression 21 operands: lhs = Counter(21), rhs = Counter(22) +- expression 22 operands: lhs = Counter(23), rhs = Counter(24) +- expression 23 operands: lhs = Counter(22), rhs = Expression(24, Add) +- expression 24 operands: lhs = Counter(23), rhs = Counter(24) +- expression 25 operands: lhs = Counter(27), rhs = Expression(49, Add) +- expression 26 operands: lhs = Counter(28), rhs = Counter(29) +- expression 27 operands: lhs = Counter(25), rhs = Counter(27) +- expression 28 operands: lhs = Expression(32, Sub), rhs = Counter(8) +- expression 29 operands: lhs = Counter(25), rhs = Counter(27) +- expression 30 operands: lhs = Expression(31, Sub), rhs = Counter(31) +- expression 31 operands: lhs = Expression(32, Sub), rhs = Counter(8) +- expression 32 operands: lhs = Counter(25), rhs = Counter(27) +- expression 33 operands: lhs = Counter(28), rhs = Counter(29) +- expression 34 operands: lhs = Counter(4), rhs = Expression(53, Add) +- expression 35 operands: lhs = Counter(5), rhs = Counter(6) +- expression 36 operands: lhs = Counter(27), rhs = Expression(49, Add) +- expression 37 operands: lhs = Counter(28), rhs = Counter(29) +- expression 38 operands: lhs = Expression(48, Add), rhs = Counter(4) +- expression 39 operands: lhs = Counter(27), rhs = Expression(49, Add) +- expression 40 operands: lhs = Counter(28), rhs = Counter(29) +- expression 41 operands: lhs = Expression(47, Sub), rhs = Counter(7) +- expression 42 operands: lhs = Expression(48, Add), rhs = Counter(4) +- expression 43 operands: lhs = Counter(27), rhs = Expression(49, Add) +- expression 44 operands: lhs = Counter(28), rhs = Counter(29) +- expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(34) +- expression 46 operands: lhs = Expression(47, Sub), rhs = Counter(7) +- expression 47 operands: lhs = Expression(48, Add), rhs = Counter(4) +- expression 48 operands: lhs = Counter(27), rhs = Expression(49, Add) +- expression 49 operands: lhs = Counter(28), rhs = Counter(29) +- expression 50 operands: lhs = Counter(5), rhs = Counter(6) +- expression 51 operands: lhs = Expression(52, Add), rhs = Expression(54, Add) +- expression 52 operands: lhs = Counter(4), rhs = Expression(53, Add) +- expression 53 operands: lhs = Counter(5), rhs = Counter(6) +- expression 54 operands: lhs = Expression(55, Add), rhs = Expression(58, Sub) +- expression 55 operands: lhs = Expression(56, Add), rhs = Expression(57, Add) +- expression 56 operands: lhs = Counter(7), rhs = Counter(8) +- expression 57 operands: lhs = Counter(9), rhs = Counter(10) +- expression 58 operands: lhs = Expression(59, Sub), rhs = Counter(3) +- expression 59 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 68 - Code(Counter(0)) at (prev + 3, 1) to (start + 2, 12) - Code(Counter(1)) at (prev + 2, 13) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Expression(0, Add)) at (prev + 3, 9) to (start + 0, 10) = (c2 + (c11 + c12)) -- Code(Expression(78, Add)) at (prev + 0, 16) to (start + 0, 29) - = (c1 + Zero) +- Code(Counter(1)) at (prev + 0, 16) to (start + 0, 29) - Code(Counter(2)) at (prev + 1, 9) to (start + 1, 10) -- Code(Expression(77, Sub)) at (prev + 2, 15) to (start + 0, 28) - = ((c1 + Zero) - c2) +- Code(Expression(59, Sub)) at (prev + 2, 15) to (start + 0, 28) + = (c1 - c2) - Code(Counter(3)) at (prev + 1, 12) to (start + 0, 25) -- Code(Expression(5, Sub)) at (prev + 0, 29) to (start + 0, 42) +- Code(Expression(3, Sub)) at (prev + 0, 29) to (start + 0, 42) = (c3 - c14) - Code(Counter(16)) at (prev + 0, 46) to (start + 0, 60) - Code(Counter(11)) at (prev + 0, 61) to (start + 2, 10) - Code(Counter(12)) at (prev + 2, 10) to (start + 0, 11) -- Code(Expression(6, Add)) at (prev + 1, 9) to (start + 1, 18) +- Code(Expression(4, Add)) at (prev + 1, 9) to (start + 1, 18) = (c11 + c12) -- Code(Expression(76, Sub)) at (prev + 3, 9) to (start + 0, 15) - = (((c1 + Zero) - c2) - c3) -- Code(Expression(10, Add)) at (prev + 3, 9) to (start + 1, 12) - = ((c2 + (c11 + c12)) + Zero) +- Code(Expression(58, Sub)) at (prev + 3, 9) to (start + 0, 15) + = ((c1 - c2) - c3) +- Code(Expression(0, Add)) at (prev + 3, 9) to (start + 1, 12) + = (c2 + (c11 + c12)) - Code(Counter(13)) at (prev + 1, 13) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) -- Code(Expression(20, Add)) at (prev + 2, 8) to (start + 0, 21) - = (c13 + Zero) +- Code(Counter(13)) at (prev + 2, 8) to (start + 0, 21) - Code(Counter(15)) at (prev + 0, 22) to (start + 2, 6) -- Code(Expression(19, Sub)) at (prev + 2, 15) to (start + 0, 28) - = ((c13 + Zero) - c15) -- Code(Expression(18, Sub)) at (prev + 1, 12) to (start + 0, 25) - = (((c13 + Zero) - c15) - c10) -- Code(Expression(17, Sub)) at (prev + 0, 29) to (start + 0, 42) - = ((((c13 + Zero) - c15) - c10) - c20) +- Code(Expression(12, Sub)) at (prev + 2, 15) to (start + 0, 28) + = (c13 - c15) +- Code(Expression(11, Sub)) at (prev + 1, 12) to (start + 0, 25) + = ((c13 - c15) - c10) +- Code(Expression(10, Sub)) at (prev + 0, 29) to (start + 0, 42) + = (((c13 - c15) - c10) - c20) - Code(Counter(26)) at (prev + 0, 46) to (start + 0, 60) - Code(Counter(17)) at (prev + 0, 61) to (start + 2, 10) - Code(Counter(18)) at (prev + 2, 10) to (start + 0, 11) -- Code(Expression(23, Add)) at (prev + 1, 9) to (start + 0, 23) +- Code(Expression(15, Add)) at (prev + 1, 9) to (start + 0, 23) = (c17 + c18) - Code(Counter(10)) at (prev + 2, 9) to (start + 0, 15) -- Code(Expression(22, Add)) at (prev + 3, 8) to (start + 0, 12) +- Code(Expression(14, Add)) at (prev + 3, 8) to (start + 0, 12) = (c15 + (c17 + c18)) - Code(Counter(19)) at (prev + 1, 13) to (start + 1, 16) - Code(Counter(21)) at (prev + 1, 17) to (start + 2, 10) - Code(Zero) at (prev + 2, 10) to (start + 0, 11) -- Code(Expression(33, Add)) at (prev + 2, 12) to (start + 0, 25) - = (c21 + Zero) +- Code(Counter(21)) at (prev + 2, 12) to (start + 0, 25) - Code(Counter(22)) at (prev + 0, 26) to (start + 2, 10) -- Code(Expression(32, Sub)) at (prev + 3, 17) to (start + 0, 30) - = ((c21 + Zero) - c22) -- Code(Expression(31, Sub)) at (prev + 1, 16) to (start + 0, 29) - = (((c21 + Zero) - c22) - c9) -- Code(Expression(30, Sub)) at (prev + 0, 33) to (start + 0, 46) - = ((((c21 + Zero) - c22) - c9) - c30) +- Code(Expression(21, Sub)) at (prev + 3, 17) to (start + 0, 30) + = (c21 - c22) +- Code(Expression(20, Sub)) at (prev + 1, 16) to (start + 0, 29) + = ((c21 - c22) - c9) +- Code(Expression(19, Sub)) at (prev + 0, 33) to (start + 0, 46) + = (((c21 - c22) - c9) - c30) - Code(Counter(32)) at (prev + 0, 50) to (start + 0, 64) - Code(Counter(23)) at (prev + 0, 65) to (start + 2, 14) - Code(Counter(24)) at (prev + 2, 14) to (start + 0, 15) -- Code(Expression(37, Add)) at (prev + 1, 13) to (start + 0, 27) +- Code(Expression(24, Add)) at (prev + 1, 13) to (start + 0, 27) = (c23 + c24) - Code(Counter(9)) at (prev + 2, 13) to (start + 0, 19) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) -- Code(Expression(35, Add)) at (prev + 3, 9) to (start + 1, 12) - = ((c22 + (c23 + c24)) + Zero) +- Code(Expression(23, Add)) at (prev + 3, 9) to (start + 1, 12) + = (c22 + (c23 + c24)) - Code(Counter(25)) at (prev + 1, 13) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) -- Code(Expression(66, Add)) at (prev + 2, 9) to (start + 0, 10) +- Code(Expression(48, Add)) at (prev + 2, 9) to (start + 0, 10) = (c27 + (c28 + c29)) -- Code(Expression(49, Add)) at (prev + 0, 16) to (start + 0, 29) - = (c25 + Zero) +- Code(Counter(25)) at (prev + 0, 16) to (start + 0, 29) - Code(Counter(27)) at (prev + 0, 30) to (start + 2, 6) -- Code(Expression(48, Sub)) at (prev + 2, 15) to (start + 0, 28) - = ((c25 + Zero) - c27) -- Code(Expression(47, Sub)) at (prev + 1, 12) to (start + 0, 25) - = (((c25 + Zero) - c27) - c8) -- Code(Expression(46, Sub)) at (prev + 0, 29) to (start + 0, 42) - = ((((c25 + Zero) - c27) - c8) - c31) +- Code(Expression(32, Sub)) at (prev + 2, 15) to (start + 0, 28) + = (c25 - c27) +- Code(Expression(31, Sub)) at (prev + 1, 12) to (start + 0, 25) + = ((c25 - c27) - c8) +- Code(Expression(30, Sub)) at (prev + 0, 29) to (start + 0, 42) + = (((c25 - c27) - c8) - c31) - Code(Counter(33)) at (prev + 0, 46) to (start + 0, 60) - Code(Counter(28)) at (prev + 0, 61) to (start + 2, 10) - Code(Counter(29)) at (prev + 2, 10) to (start + 0, 11) -- Code(Expression(67, Add)) at (prev + 1, 9) to (start + 0, 23) +- Code(Expression(49, Add)) at (prev + 1, 9) to (start + 0, 23) = (c28 + c29) - Code(Counter(8)) at (prev + 2, 13) to (start + 2, 15) -- Code(Expression(70, Add)) at (prev + 5, 9) to (start + 0, 10) +- Code(Expression(52, Add)) at (prev + 5, 9) to (start + 0, 10) = (c4 + (c5 + c6)) -- Code(Expression(53, Add)) at (prev + 0, 16) to (start + 0, 29) - = ((c27 + (c28 + c29)) + Zero) +- Code(Expression(48, Add)) at (prev + 0, 16) to (start + 0, 29) + = (c27 + (c28 + c29)) - Code(Counter(4)) at (prev + 0, 30) to (start + 2, 6) -- Code(Expression(65, Sub)) at (prev + 2, 15) to (start + 0, 28) +- Code(Expression(47, Sub)) at (prev + 2, 15) to (start + 0, 28) = ((c27 + (c28 + c29)) - c4) -- Code(Expression(64, Sub)) at (prev + 1, 12) to (start + 0, 25) +- Code(Expression(46, Sub)) at (prev + 1, 12) to (start + 0, 25) = (((c27 + (c28 + c29)) - c4) - c7) -- Code(Expression(63, Sub)) at (prev + 0, 29) to (start + 0, 42) +- Code(Expression(45, Sub)) at (prev + 0, 29) to (start + 0, 42) = ((((c27 + (c28 + c29)) - c4) - c7) - c34) - Code(Counter(35)) at (prev + 0, 46) to (start + 0, 60) - Code(Counter(5)) at (prev + 0, 61) to (start + 2, 10) - Code(Counter(6)) at (prev + 2, 10) to (start + 0, 11) -- Code(Expression(71, Add)) at (prev + 1, 9) to (start + 0, 23) +- Code(Expression(53, Add)) at (prev + 1, 9) to (start + 0, 23) = (c5 + c6) - Code(Counter(7)) at (prev + 2, 9) to (start + 0, 15) -- Code(Expression(69, Add)) at (prev + 2, 1) to (start + 0, 2) - = ((c4 + (c5 + c6)) + (((c7 + c8) + (c9 + c10)) + (((c1 + Zero) - c2) - c3))) +- Code(Expression(51, Add)) at (prev + 2, 1) to (start + 0, 2) + = ((c4 + (c5 + c6)) + (((c7 + c8) + (c9 + c10)) + ((c1 - c2) - c3))) diff --git a/tests/coverage-map/status-quo/drop_trait.cov-map b/tests/coverage-map/status-quo/drop_trait.cov-map index 203d1048b0547..cf3df9fce1d23 100644 --- a/tests/coverage-map/status-quo/drop_trait.cov-map +++ b/tests/coverage-map/status-quo/drop_trait.cov-map @@ -7,15 +7,13 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 9, 5) to (start + 2, 6) Function name: drop_trait::main -Raw bytes (26): 0x[01, 01, 01, 05, 00, 04, 01, 0e, 01, 05, 0c, 05, 06, 09, 01, 16, 00, 02, 06, 04, 0b, 03, 05, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 0e, 01, 05, 0c, 05, 06, 09, 01, 16, 00, 02, 06, 04, 0b, 05, 05, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(1), rhs = Zero +Number of expressions: 0 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 14, 1) to (start + 5, 12) - Code(Counter(1)) at (prev + 6, 9) to (start + 1, 22) - Code(Zero) at (prev + 2, 6) to (start + 4, 11) -- Code(Expression(0, Add)) at (prev + 5, 1) to (start + 0, 2) - = (c1 + Zero) +- Code(Counter(1)) at (prev + 5, 1) to (start + 0, 2) diff --git a/tests/coverage-map/status-quo/generics.cov-map b/tests/coverage-map/status-quo/generics.cov-map index c28e9c1fa93f4..b7e3c772dd237 100644 --- a/tests/coverage-map/status-quo/generics.cov-map +++ b/tests/coverage-map/status-quo/generics.cov-map @@ -31,15 +31,13 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 10, 5) to (start + 2, 6) Function name: generics::main -Raw bytes (26): 0x[01, 01, 01, 05, 00, 04, 01, 16, 01, 08, 0c, 05, 09, 09, 01, 16, 00, 02, 06, 08, 0b, 03, 09, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 01, 08, 0c, 05, 09, 09, 01, 16, 00, 02, 06, 08, 0b, 05, 09, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(1), rhs = Zero +Number of expressions: 0 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 22, 1) to (start + 8, 12) - Code(Counter(1)) at (prev + 9, 9) to (start + 1, 22) - Code(Zero) at (prev + 2, 6) to (start + 8, 11) -- Code(Expression(0, Add)) at (prev + 9, 1) to (start + 0, 2) - = (c1 + Zero) +- Code(Counter(1)) at (prev + 9, 1) to (start + 0, 2) diff --git a/tests/coverage-map/status-quo/loops_branches.cov-map b/tests/coverage-map/status-quo/loops_branches.cov-map index 3e442ec01c051..199f9aa9830f8 100644 --- a/tests/coverage-map/status-quo/loops_branches.cov-map +++ b/tests/coverage-map/status-quo/loops_branches.cov-map @@ -1,58 +1,45 @@ Function name: ::fmt -Raw bytes (251): 0x[01, 01, 32, 05, 09, 00, 02, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, c3, 01, c7, 01, 0d, 00, 11, 15, ba, 01, 00, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, ba, 01, 15, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, b6, 01, 1d, ba, 01, 15, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, 00, b2, 01, b6, 01, 1d, ba, 01, 15, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, af, 01, 11, 00, b2, 01, b6, 01, 1d, ba, 01, 15, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, 25, a7, 01, aa, 01, 19, af, 01, 11, 00, b2, 01, b6, 01, 1d, ba, 01, 15, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 01, 12, 02, 02, 0e, 00, 0f, 07, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, ba, 01, 03, 0d, 00, 0e, bf, 01, 00, 12, 00, 17, 27, 01, 10, 00, 14, b6, 01, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, b2, 01, 01, 12, 00, 13, af, 01, 01, 11, 00, 22, aa, 01, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, a3, 01, 01, 05, 00, 06] +Raw bytes (210): 0x[01, 01, 25, 05, 09, 8f, 01, 19, 0d, 93, 01, 11, 15, 0d, 93, 01, 11, 15, 8f, 01, 19, 0d, 93, 01, 11, 15, 8a, 01, 15, 8f, 01, 19, 0d, 93, 01, 11, 15, 86, 01, 1d, 8a, 01, 15, 8f, 01, 19, 0d, 93, 01, 11, 15, 86, 01, 1d, 8a, 01, 15, 8f, 01, 19, 0d, 93, 01, 11, 15, 82, 01, 11, 86, 01, 1d, 8a, 01, 15, 8f, 01, 19, 0d, 93, 01, 11, 15, 25, 7b, 7e, 19, 82, 01, 11, 86, 01, 1d, 8a, 01, 15, 8f, 01, 19, 0d, 93, 01, 11, 15, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 01, 12, 02, 02, 0e, 00, 0f, 02, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 8a, 01, 03, 0d, 00, 0e, 8f, 01, 00, 12, 00, 17, 8a, 01, 01, 10, 00, 14, 86, 01, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 82, 01, 01, 12, 00, 13, 82, 01, 01, 11, 00, 22, 7e, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, 77, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 -Number of expressions: 50 +Number of expressions: 37 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) -- expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) -- expression 2 operands: lhs = Expression(47, Add), rhs = Counter(6) -- expression 3 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) -- expression 4 operands: lhs = Counter(3), rhs = Zero +- expression 1 operands: lhs = Expression(35, Add), rhs = Counter(6) +- expression 2 operands: lhs = Counter(3), rhs = Expression(36, Add) +- expression 3 operands: lhs = Counter(4), rhs = Counter(5) +- expression 4 operands: lhs = Counter(3), rhs = Expression(36, Add) - expression 5 operands: lhs = Counter(4), rhs = Counter(5) -- expression 6 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) -- expression 7 operands: lhs = Counter(3), rhs = Zero +- expression 6 operands: lhs = Expression(35, Add), rhs = Counter(6) +- expression 7 operands: lhs = Counter(3), rhs = Expression(36, Add) - expression 8 operands: lhs = Counter(4), rhs = Counter(5) -- expression 9 operands: lhs = Expression(46, Sub), rhs = Zero -- expression 10 operands: lhs = Expression(47, Add), rhs = Counter(6) -- expression 11 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) -- expression 12 operands: lhs = Counter(3), rhs = Zero -- expression 13 operands: lhs = Counter(4), rhs = Counter(5) -- expression 14 operands: lhs = Expression(46, Sub), rhs = Counter(5) -- expression 15 operands: lhs = Expression(47, Add), rhs = Counter(6) -- expression 16 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) -- expression 17 operands: lhs = Counter(3), rhs = Zero -- expression 18 operands: lhs = Counter(4), rhs = Counter(5) -- expression 19 operands: lhs = Expression(45, Sub), rhs = Counter(7) -- expression 20 operands: lhs = Expression(46, Sub), rhs = Counter(5) -- expression 21 operands: lhs = Expression(47, Add), rhs = Counter(6) -- expression 22 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) -- expression 23 operands: lhs = Counter(3), rhs = Zero -- expression 24 operands: lhs = Counter(4), rhs = Counter(5) -- expression 25 operands: lhs = Zero, rhs = Expression(44, Sub) -- expression 26 operands: lhs = Expression(45, Sub), rhs = Counter(7) -- expression 27 operands: lhs = Expression(46, Sub), rhs = Counter(5) -- expression 28 operands: lhs = Expression(47, Add), rhs = Counter(6) -- expression 29 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) -- expression 30 operands: lhs = Counter(3), rhs = Zero -- expression 31 operands: lhs = Counter(4), rhs = Counter(5) -- expression 32 operands: lhs = Expression(43, Add), rhs = Counter(4) -- expression 33 operands: lhs = Zero, rhs = Expression(44, Sub) -- expression 34 operands: lhs = Expression(45, Sub), rhs = Counter(7) -- expression 35 operands: lhs = Expression(46, Sub), rhs = Counter(5) -- expression 36 operands: lhs = Expression(47, Add), rhs = Counter(6) -- expression 37 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) -- expression 38 operands: lhs = Counter(3), rhs = Zero -- expression 39 operands: lhs = Counter(4), rhs = Counter(5) -- expression 40 operands: lhs = Counter(9), rhs = Expression(41, Add) -- expression 41 operands: lhs = Expression(42, Sub), rhs = Counter(6) -- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(4) -- expression 43 operands: lhs = Zero, rhs = Expression(44, Sub) -- expression 44 operands: lhs = Expression(45, Sub), rhs = Counter(7) -- expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(5) -- expression 46 operands: lhs = Expression(47, Add), rhs = Counter(6) -- expression 47 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) -- expression 48 operands: lhs = Counter(3), rhs = Zero -- expression 49 operands: lhs = Counter(4), rhs = Counter(5) +- expression 9 operands: lhs = Expression(34, Sub), rhs = Counter(5) +- expression 10 operands: lhs = Expression(35, Add), rhs = Counter(6) +- expression 11 operands: lhs = Counter(3), rhs = Expression(36, Add) +- expression 12 operands: lhs = Counter(4), rhs = Counter(5) +- expression 13 operands: lhs = Expression(33, Sub), rhs = Counter(7) +- expression 14 operands: lhs = Expression(34, Sub), rhs = Counter(5) +- expression 15 operands: lhs = Expression(35, Add), rhs = Counter(6) +- expression 16 operands: lhs = Counter(3), rhs = Expression(36, Add) +- expression 17 operands: lhs = Counter(4), rhs = Counter(5) +- expression 18 operands: lhs = Expression(33, Sub), rhs = Counter(7) +- expression 19 operands: lhs = Expression(34, Sub), rhs = Counter(5) +- expression 20 operands: lhs = Expression(35, Add), rhs = Counter(6) +- expression 21 operands: lhs = Counter(3), rhs = Expression(36, Add) +- expression 22 operands: lhs = Counter(4), rhs = Counter(5) +- expression 23 operands: lhs = Expression(32, Sub), rhs = Counter(4) +- expression 24 operands: lhs = Expression(33, Sub), rhs = Counter(7) +- expression 25 operands: lhs = Expression(34, Sub), rhs = Counter(5) +- expression 26 operands: lhs = Expression(35, Add), rhs = Counter(6) +- expression 27 operands: lhs = Counter(3), rhs = Expression(36, Add) +- expression 28 operands: lhs = Counter(4), rhs = Counter(5) +- expression 29 operands: lhs = Counter(9), rhs = Expression(30, Add) +- expression 30 operands: lhs = Expression(31, Sub), rhs = Counter(6) +- expression 31 operands: lhs = Expression(32, Sub), rhs = Counter(4) +- expression 32 operands: lhs = Expression(33, Sub), rhs = Counter(7) +- expression 33 operands: lhs = Expression(34, Sub), rhs = Counter(5) +- expression 34 operands: lhs = Expression(35, Add), rhs = Counter(6) +- expression 35 operands: lhs = Counter(3), rhs = Expression(36, Add) +- expression 36 operands: lhs = Counter(4), rhs = Counter(5) Number of file 0 mappings: 20 - Code(Counter(0)) at (prev + 9, 5) to (start + 1, 16) - Code(Counter(1)) at (prev + 2, 16) to (start + 0, 21) @@ -60,88 +47,83 @@ Number of file 0 mappings: 20 - Code(Zero) at (prev + 0, 28) to (start + 1, 18) - Code(Expression(0, Sub)) at (prev + 2, 14) to (start + 0, 15) = (c1 - c2) -- Code(Expression(1, Add)) at (prev + 1, 13) to (start + 0, 30) - = (Zero + (c1 - c2)) +- Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 30) + = (c1 - c2) - Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31) - Code(Zero) at (prev + 1, 16) to (start + 1, 10) -- Code(Expression(46, Sub)) at (prev + 3, 13) to (start + 0, 14) - = (((c3 + Zero) + (c4 + c5)) - c6) -- Code(Expression(47, Add)) at (prev + 0, 18) to (start + 0, 23) - = ((c3 + Zero) + (c4 + c5)) -- Code(Expression(9, Add)) at (prev + 1, 16) to (start + 0, 20) - = ((((c3 + Zero) + (c4 + c5)) - c6) + Zero) -- Code(Expression(45, Sub)) at (prev + 1, 20) to (start + 0, 25) - = ((((c3 + Zero) + (c4 + c5)) - c6) - c5) +- Code(Expression(34, Sub)) at (prev + 3, 13) to (start + 0, 14) + = ((c3 + (c4 + c5)) - c6) +- Code(Expression(35, Add)) at (prev + 0, 18) to (start + 0, 23) + = (c3 + (c4 + c5)) +- Code(Expression(34, Sub)) at (prev + 1, 16) to (start + 0, 20) + = ((c3 + (c4 + c5)) - c6) +- Code(Expression(33, Sub)) at (prev + 1, 20) to (start + 0, 25) + = (((c3 + (c4 + c5)) - c6) - c5) - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) -- Code(Expression(44, Sub)) at (prev + 1, 18) to (start + 0, 19) - = (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7) -- Code(Expression(43, Add)) at (prev + 1, 17) to (start + 0, 34) - = (Zero + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) -- Code(Expression(42, Sub)) at (prev + 0, 34) to (start + 0, 35) - = ((Zero + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) - c4) +- Code(Expression(32, Sub)) at (prev + 1, 18) to (start + 0, 19) + = ((((c3 + (c4 + c5)) - c6) - c5) - c7) +- Code(Expression(32, Sub)) at (prev + 1, 17) to (start + 0, 34) + = ((((c3 + (c4 + c5)) - c6) - c5) - c7) +- Code(Expression(31, Sub)) at (prev + 0, 34) to (start + 0, 35) + = (((((c3 + (c4 + c5)) - c6) - c5) - c7) - c4) - Code(Zero) at (prev + 1, 20) to (start + 1, 14) - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) -- Code(Expression(40, Add)) at (prev + 1, 5) to (start + 0, 6) - = (c9 + (((Zero + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) - c4) + c6)) +- Code(Expression(29, Add)) at (prev + 1, 5) to (start + 0, 6) + = (c9 + ((((((c3 + (c4 + c5)) - c6) - c5) - c7) - c4) + c6)) Function name: ::fmt -Raw bytes (255): 0x[01, 01, 34, 01, 05, 02, 09, 00, 0e, 02, 09, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, c7, 01, cb, 01, 05, 0d, 11, 15, be, 01, 00, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, be, 01, 11, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, ba, 01, 1d, be, 01, 11, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, 00, b6, 01, ba, 01, 1d, be, 01, 11, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, b3, 01, 15, 00, b6, 01, ba, 01, 1d, be, 01, 11, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, ae, 01, cf, 01, b3, 01, 15, 00, b6, 01, ba, 01, 1d, be, 01, 11, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, 19, 25, 14, 01, 23, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 0e, 01, 0e, 00, 0f, 0b, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, be, 01, 02, 0d, 00, 0e, c3, 01, 00, 12, 00, 17, 2f, 01, 10, 00, 15, 00, 00, 16, 01, 0e, ba, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, b6, 01, 01, 12, 00, 13, b3, 01, 01, 11, 00, 22, ae, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, ab, 01, 01, 05, 00, 06] +Raw bytes (242): 0x[01, 01, 2f, 01, 05, 02, 09, 02, 09, af, 01, 19, b3, 01, b7, 01, 05, 0d, 11, 15, b3, 01, b7, 01, 05, 0d, 11, 15, af, 01, 19, b3, 01, b7, 01, 05, 0d, 11, 15, aa, 01, 11, af, 01, 19, b3, 01, b7, 01, 05, 0d, 11, 15, a6, 01, 1d, aa, 01, 11, af, 01, 19, b3, 01, b7, 01, 05, 0d, 11, 15, a6, 01, 1d, aa, 01, 11, af, 01, 19, b3, 01, b7, 01, 05, 0d, 11, 15, a2, 01, 15, a6, 01, 1d, aa, 01, 11, af, 01, 19, b3, 01, b7, 01, 05, 0d, 11, 15, 9e, 01, bb, 01, a2, 01, 15, a6, 01, 1d, aa, 01, 11, af, 01, 19, b3, 01, b7, 01, 05, 0d, 11, 15, 19, 25, 14, 01, 23, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 0a, 01, 0e, 00, 0f, 0a, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, aa, 01, 02, 0d, 00, 0e, af, 01, 00, 12, 00, 17, aa, 01, 01, 10, 00, 15, 00, 00, 16, 01, 0e, a6, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, a2, 01, 01, 12, 00, 13, a2, 01, 01, 11, 00, 22, 9e, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, 9b, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 -Number of expressions: 52 +Number of expressions: 47 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Expression(0, Sub), rhs = Counter(2) -- expression 2 operands: lhs = Zero, rhs = Expression(3, Sub) -- expression 3 operands: lhs = Expression(0, Sub), rhs = Counter(2) -- expression 4 operands: lhs = Expression(48, Add), rhs = Counter(6) -- expression 5 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) -- expression 6 operands: lhs = Counter(1), rhs = Counter(3) -- expression 7 operands: lhs = Counter(4), rhs = Counter(5) -- expression 8 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) -- expression 9 operands: lhs = Counter(1), rhs = Counter(3) -- expression 10 operands: lhs = Counter(4), rhs = Counter(5) -- expression 11 operands: lhs = Expression(47, Sub), rhs = Zero -- expression 12 operands: lhs = Expression(48, Add), rhs = Counter(6) -- expression 13 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) -- expression 14 operands: lhs = Counter(1), rhs = Counter(3) -- expression 15 operands: lhs = Counter(4), rhs = Counter(5) -- expression 16 operands: lhs = Expression(47, Sub), rhs = Counter(4) -- expression 17 operands: lhs = Expression(48, Add), rhs = Counter(6) -- expression 18 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) -- expression 19 operands: lhs = Counter(1), rhs = Counter(3) -- expression 20 operands: lhs = Counter(4), rhs = Counter(5) -- expression 21 operands: lhs = Expression(46, Sub), rhs = Counter(7) -- expression 22 operands: lhs = Expression(47, Sub), rhs = Counter(4) -- expression 23 operands: lhs = Expression(48, Add), rhs = Counter(6) -- expression 24 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) -- expression 25 operands: lhs = Counter(1), rhs = Counter(3) -- expression 26 operands: lhs = Counter(4), rhs = Counter(5) -- expression 27 operands: lhs = Zero, rhs = Expression(45, Sub) -- expression 28 operands: lhs = Expression(46, Sub), rhs = Counter(7) -- expression 29 operands: lhs = Expression(47, Sub), rhs = Counter(4) -- expression 30 operands: lhs = Expression(48, Add), rhs = Counter(6) -- expression 31 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) -- expression 32 operands: lhs = Counter(1), rhs = Counter(3) -- expression 33 operands: lhs = Counter(4), rhs = Counter(5) -- expression 34 operands: lhs = Expression(44, Add), rhs = Counter(5) -- expression 35 operands: lhs = Zero, rhs = Expression(45, Sub) -- expression 36 operands: lhs = Expression(46, Sub), rhs = Counter(7) -- expression 37 operands: lhs = Expression(47, Sub), rhs = Counter(4) -- expression 38 operands: lhs = Expression(48, Add), rhs = Counter(6) -- expression 39 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) -- expression 40 operands: lhs = Counter(1), rhs = Counter(3) -- expression 41 operands: lhs = Counter(4), rhs = Counter(5) -- expression 42 operands: lhs = Expression(43, Sub), rhs = Expression(51, Add) -- expression 43 operands: lhs = Expression(44, Add), rhs = Counter(5) -- expression 44 operands: lhs = Zero, rhs = Expression(45, Sub) -- expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(7) -- expression 46 operands: lhs = Expression(47, Sub), rhs = Counter(4) -- expression 47 operands: lhs = Expression(48, Add), rhs = Counter(6) -- expression 48 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) -- expression 49 operands: lhs = Counter(1), rhs = Counter(3) -- expression 50 operands: lhs = Counter(4), rhs = Counter(5) -- expression 51 operands: lhs = Counter(6), rhs = Counter(9) +- expression 2 operands: lhs = Expression(0, Sub), rhs = Counter(2) +- expression 3 operands: lhs = Expression(43, Add), rhs = Counter(6) +- expression 4 operands: lhs = Expression(44, Add), rhs = Expression(45, Add) +- expression 5 operands: lhs = Counter(1), rhs = Counter(3) +- expression 6 operands: lhs = Counter(4), rhs = Counter(5) +- expression 7 operands: lhs = Expression(44, Add), rhs = Expression(45, Add) +- expression 8 operands: lhs = Counter(1), rhs = Counter(3) +- expression 9 operands: lhs = Counter(4), rhs = Counter(5) +- expression 10 operands: lhs = Expression(43, Add), rhs = Counter(6) +- expression 11 operands: lhs = Expression(44, Add), rhs = Expression(45, Add) +- expression 12 operands: lhs = Counter(1), rhs = Counter(3) +- expression 13 operands: lhs = Counter(4), rhs = Counter(5) +- expression 14 operands: lhs = Expression(42, Sub), rhs = Counter(4) +- expression 15 operands: lhs = Expression(43, Add), rhs = Counter(6) +- expression 16 operands: lhs = Expression(44, Add), rhs = Expression(45, Add) +- expression 17 operands: lhs = Counter(1), rhs = Counter(3) +- expression 18 operands: lhs = Counter(4), rhs = Counter(5) +- expression 19 operands: lhs = Expression(41, Sub), rhs = Counter(7) +- expression 20 operands: lhs = Expression(42, Sub), rhs = Counter(4) +- expression 21 operands: lhs = Expression(43, Add), rhs = Counter(6) +- expression 22 operands: lhs = Expression(44, Add), rhs = Expression(45, Add) +- expression 23 operands: lhs = Counter(1), rhs = Counter(3) +- expression 24 operands: lhs = Counter(4), rhs = Counter(5) +- expression 25 operands: lhs = Expression(41, Sub), rhs = Counter(7) +- expression 26 operands: lhs = Expression(42, Sub), rhs = Counter(4) +- expression 27 operands: lhs = Expression(43, Add), rhs = Counter(6) +- expression 28 operands: lhs = Expression(44, Add), rhs = Expression(45, Add) +- expression 29 operands: lhs = Counter(1), rhs = Counter(3) +- expression 30 operands: lhs = Counter(4), rhs = Counter(5) +- expression 31 operands: lhs = Expression(40, Sub), rhs = Counter(5) +- expression 32 operands: lhs = Expression(41, Sub), rhs = Counter(7) +- expression 33 operands: lhs = Expression(42, Sub), rhs = Counter(4) +- expression 34 operands: lhs = Expression(43, Add), rhs = Counter(6) +- expression 35 operands: lhs = Expression(44, Add), rhs = Expression(45, Add) +- expression 36 operands: lhs = Counter(1), rhs = Counter(3) +- expression 37 operands: lhs = Counter(4), rhs = Counter(5) +- expression 38 operands: lhs = Expression(39, Sub), rhs = Expression(46, Add) +- expression 39 operands: lhs = Expression(40, Sub), rhs = Counter(5) +- expression 40 operands: lhs = Expression(41, Sub), rhs = Counter(7) +- expression 41 operands: lhs = Expression(42, Sub), rhs = Counter(4) +- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(6) +- expression 43 operands: lhs = Expression(44, Add), rhs = Expression(45, Add) +- expression 44 operands: lhs = Counter(1), rhs = Counter(3) +- expression 45 operands: lhs = Counter(4), rhs = Counter(5) +- expression 46 operands: lhs = Counter(6), rhs = Counter(9) Number of file 0 mappings: 20 - Code(Counter(0)) at (prev + 35, 5) to (start + 1, 17) - Code(Zero) at (prev + 1, 18) to (start + 1, 10) @@ -149,31 +131,31 @@ Number of file 0 mappings: 20 = (c0 - c1) - Code(Zero) at (prev + 1, 23) to (start + 0, 27) - Code(Zero) at (prev + 0, 28) to (start + 0, 30) -- Code(Expression(3, Sub)) at (prev + 1, 14) to (start + 0, 15) +- Code(Expression(2, Sub)) at (prev + 1, 14) to (start + 0, 15) + = ((c0 - c1) - c2) +- Code(Expression(2, Sub)) at (prev + 1, 13) to (start + 0, 30) = ((c0 - c1) - c2) -- Code(Expression(2, Add)) at (prev + 1, 13) to (start + 0, 30) - = (Zero + ((c0 - c1) - c2)) - Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31) -- Code(Expression(47, Sub)) at (prev + 2, 13) to (start + 0, 14) +- Code(Expression(42, Sub)) at (prev + 2, 13) to (start + 0, 14) = (((c1 + c3) + (c4 + c5)) - c6) -- Code(Expression(48, Add)) at (prev + 0, 18) to (start + 0, 23) +- Code(Expression(43, Add)) at (prev + 0, 18) to (start + 0, 23) = ((c1 + c3) + (c4 + c5)) -- Code(Expression(11, Add)) at (prev + 1, 16) to (start + 0, 21) - = ((((c1 + c3) + (c4 + c5)) - c6) + Zero) +- Code(Expression(42, Sub)) at (prev + 1, 16) to (start + 0, 21) + = (((c1 + c3) + (c4 + c5)) - c6) - Code(Zero) at (prev + 0, 22) to (start + 1, 14) -- Code(Expression(46, Sub)) at (prev + 2, 20) to (start + 0, 25) +- Code(Expression(41, Sub)) at (prev + 2, 20) to (start + 0, 25) = ((((c1 + c3) + (c4 + c5)) - c6) - c4) - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) -- Code(Expression(45, Sub)) at (prev + 1, 18) to (start + 0, 19) +- Code(Expression(40, Sub)) at (prev + 1, 18) to (start + 0, 19) + = (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7) +- Code(Expression(40, Sub)) at (prev + 1, 17) to (start + 0, 34) = (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7) -- Code(Expression(44, Add)) at (prev + 1, 17) to (start + 0, 34) - = (Zero + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) -- Code(Expression(43, Sub)) at (prev + 0, 34) to (start + 0, 35) - = ((Zero + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) - c5) +- Code(Expression(39, Sub)) at (prev + 0, 34) to (start + 0, 35) + = ((((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7) - c5) - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) -- Code(Expression(42, Add)) at (prev + 1, 5) to (start + 0, 6) - = (((Zero + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) - c5) + (c6 + c9)) +- Code(Expression(38, Add)) at (prev + 1, 5) to (start + 0, 6) + = (((((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7) - c5) + (c6 + c9)) Function name: loops_branches::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 38, 01, 05, 02] From 31dd815e2d4b8642e28b7852831e7c9c95c5031e Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 22 Aug 2023 20:30:19 +1000 Subject: [PATCH 08/11] Treat `StatementKind::Coverage` as completely opaque for SMIR purposes Coverage statements in MIR are heavily tied to internal details of the coverage implementation that are likely to change, and are unlikely to be useful to third-party tools for the foreseeable future. --- compiler/rustc_smir/src/rustc_smir/mod.rs | 56 +------------------ .../rustc_smir/src/stable_mir/mir/body.rs | 43 ++------------ 2 files changed, 5 insertions(+), 94 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index aea59c31379e7..368608b82a09d 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -15,7 +15,6 @@ use crate::stable_mir::ty::{ }; use crate::stable_mir::{self, Context}; use rustc_hir as hir; -use rustc_middle::mir::coverage::CodeRegion; use rustc_middle::mir::interpret::alloc_range; use rustc_middle::mir::{self, ConstantKind}; use rustc_middle::ty::{self, Ty, TyCtxt, Variance}; @@ -175,10 +174,7 @@ impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> { variance: variance.stable(tables), } } - Coverage(coverage) => stable_mir::mir::Statement::Coverage(stable_mir::mir::Coverage { - kind: coverage.kind.stable(tables), - code_region: coverage.code_region.as_ref().map(|reg| reg.stable(tables)), - }), + Coverage(coverage) => stable_mir::mir::Statement::Coverage(opaque(coverage)), Intrinsic(intrinstic) => { stable_mir::mir::Statement::Intrinsic(intrinstic.stable(tables)) } @@ -479,30 +475,6 @@ impl<'tcx> Stable<'tcx> for mir::Place<'tcx> { } } -impl<'tcx> Stable<'tcx> for mir::coverage::CoverageKind { - type T = stable_mir::mir::CoverageKind; - fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { - use rustc_middle::mir::coverage::CoverageKind; - match self { - CoverageKind::Counter { function_source_hash, id } => { - stable_mir::mir::CoverageKind::Counter { - function_source_hash: *function_source_hash as usize, - id: opaque(id), - } - } - CoverageKind::Expression { id, lhs, op, rhs } => { - stable_mir::mir::CoverageKind::Expression { - id: opaque(id), - lhs: opaque(lhs), - op: op.stable(tables), - rhs: opaque(rhs), - } - } - CoverageKind::Unreachable => stable_mir::mir::CoverageKind::Unreachable, - } - } -} - impl<'tcx> Stable<'tcx> for mir::UserTypeProjection { type T = stable_mir::mir::UserTypeProjection; @@ -511,18 +483,6 @@ impl<'tcx> Stable<'tcx> for mir::UserTypeProjection { } } -impl<'tcx> Stable<'tcx> for mir::coverage::Op { - type T = stable_mir::mir::Op; - - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { - use rustc_middle::mir::coverage::Op::*; - match self { - Subtract => stable_mir::mir::Op::Subtract, - Add => stable_mir::mir::Op::Add, - } - } -} - impl<'tcx> Stable<'tcx> for mir::Local { type T = stable_mir::mir::Local; fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { @@ -569,20 +529,6 @@ impl<'tcx> Stable<'tcx> for ty::UserTypeAnnotationIndex { } } -impl<'tcx> Stable<'tcx> for CodeRegion { - type T = stable_mir::mir::CodeRegion; - - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { - stable_mir::mir::CodeRegion { - file_name: self.file_name.as_str().to_string(), - start_line: self.start_line as usize, - start_col: self.start_col as usize, - end_line: self.end_line as usize, - end_col: self.end_col as usize, - } - } -} - impl<'tcx> Stable<'tcx> for mir::UnwindAction { type T = stable_mir::mir::UnwindAction; fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs index c16bd6cbd70e2..a2ab51ff8467c 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs @@ -135,9 +135,10 @@ pub enum AsyncGeneratorKind { } pub(crate) type LocalDefId = Opaque; -pub(crate) type CounterValueReference = Opaque; -pub(crate) type InjectedExpressionId = Opaque; -pub(crate) type ExpressionOperandId = Opaque; +/// [`rustc_middle::mir::Coverage`] is heavily tied to internal details of the +/// coverage implementation that are likely to change, and are unlikely to be +/// useful to third-party tools for the foreseeable future. +pub(crate) type Coverage = Opaque; /// The FakeReadCause describes the type of pattern why a FakeRead statement exists. #[derive(Clone, Debug)] @@ -166,42 +167,6 @@ pub enum Variance { Bivariant, } -#[derive(Clone, Debug)] -pub enum Op { - Subtract, - Add, -} - -#[derive(Clone, Debug)] -pub enum CoverageKind { - Counter { - function_source_hash: usize, - id: CounterValueReference, - }, - Expression { - id: InjectedExpressionId, - lhs: ExpressionOperandId, - op: Op, - rhs: ExpressionOperandId, - }, - Unreachable, -} - -#[derive(Clone, Debug)] -pub struct CodeRegion { - pub file_name: String, - pub start_line: usize, - pub start_col: usize, - pub end_line: usize, - pub end_col: usize, -} - -#[derive(Clone, Debug)] -pub struct Coverage { - pub kind: CoverageKind, - pub code_region: Option, -} - #[derive(Clone, Debug)] pub struct CopyNonOverlapping { pub src: Operand, From 43b773f4cfadf20b6bb2e4f3814cc7d24ef650d9 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Mon, 21 Aug 2023 15:31:59 +0200 Subject: [PATCH 09/11] Inline functions called from `add_coverage` This removes quite a bit of indirection and duplicated code related to getting the `FunctionCoverage`. --- .../src/coverageinfo/mod.rs | 169 +++++------------- 1 file changed, 46 insertions(+), 123 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 621fd36b2a323..c70cb670e96fb 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -16,7 +16,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_llvm::RustString; use rustc_middle::bug; -use rustc_middle::mir::coverage::{CodeRegion, CounterId, CoverageKind, ExpressionId, Op, Operand}; +use rustc_middle::mir::coverage::{CounterId, CoverageKind}; use rustc_middle::mir::Coverage; use rustc_middle::ty; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; @@ -104,144 +104,67 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { fn add_coverage(&mut self, instance: Instance<'tcx>, coverage: &Coverage) { let bx = self; + let Some(coverage_context) = bx.coverage_context() else { return }; + let mut coverage_map = coverage_context.function_coverage_map.borrow_mut(); + let func_coverage = coverage_map + .entry(instance) + .or_insert_with(|| FunctionCoverage::new(bx.tcx(), instance)); + let Coverage { kind, code_region } = coverage.clone(); match kind { CoverageKind::Counter { function_source_hash, id } => { - if bx.set_function_source_hash(instance, function_source_hash) { - // If `set_function_source_hash()` returned true, the coverage map is enabled, - // so continue adding the counter. - if let Some(code_region) = code_region { - // Note: Some counters do not have code regions, but may still be referenced - // from expressions. In that case, don't add the counter to the coverage map, - // but do inject the counter intrinsic. - bx.add_coverage_counter(instance, id, code_region); - } - - let coverageinfo = bx.tcx().coverageinfo(instance.def); - - let fn_name = bx.get_pgo_func_name_var(instance); - let hash = bx.const_u64(function_source_hash); - let num_counters = bx.const_u32(coverageinfo.num_counters); - let index = bx.const_u32(id.as_u32()); + debug!( + "ensuring function source hash is set for instance={:?}; function_source_hash={}", + instance, function_source_hash, + ); + func_coverage.set_function_source_hash(function_source_hash); + + if let Some(code_region) = code_region { + // Note: Some counters do not have code regions, but may still be referenced + // from expressions. In that case, don't add the counter to the coverage map, + // but do inject the counter intrinsic. debug!( - "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", - fn_name, hash, num_counters, index, + "adding counter to coverage_map: instance={:?}, id={:?}, region={:?}", + instance, id, code_region, ); - bx.instrprof_increment(fn_name, hash, num_counters, index); + func_coverage.add_counter(id, code_region); } + // We need to explicitly drop the `RefMut` before calling into `instrprof_increment`, + // as that needs an exclusive borrow. + drop(coverage_map); + + let coverageinfo = bx.tcx().coverageinfo(instance.def); + + let fn_name = bx.get_pgo_func_name_var(instance); + let hash = bx.const_u64(function_source_hash); + let num_counters = bx.const_u32(coverageinfo.num_counters); + let index = bx.const_u32(id.as_u32()); + debug!( + "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", + fn_name, hash, num_counters, index, + ); + bx.instrprof_increment(fn_name, hash, num_counters, index); } CoverageKind::Expression { id, lhs, op, rhs } => { - bx.add_coverage_counter_expression(instance, id, lhs, op, rhs, code_region); + debug!( + "adding counter expression to coverage_map: instance={:?}, id={:?}, {:?} {:?} {:?}; region: {:?}", + instance, id, lhs, op, rhs, code_region, + ); + func_coverage.add_counter_expression(id, lhs, op, rhs, code_region); } CoverageKind::Unreachable => { - bx.add_coverage_unreachable( - instance, - code_region.expect("unreachable regions always have code regions"), + let code_region = + code_region.expect("unreachable regions always have code regions"); + debug!( + "adding unreachable code to coverage_map: instance={:?}, at {:?}", + instance, code_region, ); + func_coverage.add_unreachable_region(code_region); } } } } -// These methods used to be part of trait `CoverageInfoBuilderMethods`, but -// after moving most coverage code out of SSA they are now just ordinary methods. -impl<'tcx> Builder<'_, '_, 'tcx> { - /// Returns true if the function source hash was added to the coverage map (even if it had - /// already been added, for this instance). Returns false *only* if `-C instrument-coverage` is - /// not enabled (a coverage map is not being generated). - fn set_function_source_hash( - &mut self, - instance: Instance<'tcx>, - function_source_hash: u64, - ) -> bool { - if let Some(coverage_context) = self.coverage_context() { - debug!( - "ensuring function source hash is set for instance={:?}; function_source_hash={}", - instance, function_source_hash, - ); - let mut coverage_map = coverage_context.function_coverage_map.borrow_mut(); - coverage_map - .entry(instance) - .or_insert_with(|| FunctionCoverage::new(self.tcx, instance)) - .set_function_source_hash(function_source_hash); - true - } else { - false - } - } - - /// Returns true if the counter was added to the coverage map; false if `-C instrument-coverage` - /// is not enabled (a coverage map is not being generated). - fn add_coverage_counter( - &mut self, - instance: Instance<'tcx>, - id: CounterId, - region: CodeRegion, - ) -> bool { - if let Some(coverage_context) = self.coverage_context() { - debug!( - "adding counter to coverage_map: instance={:?}, id={:?}, region={:?}", - instance, id, region, - ); - let mut coverage_map = coverage_context.function_coverage_map.borrow_mut(); - coverage_map - .entry(instance) - .or_insert_with(|| FunctionCoverage::new(self.tcx, instance)) - .add_counter(id, region); - true - } else { - false - } - } - - /// Returns true if the expression was added to the coverage map; false if - /// `-C instrument-coverage` is not enabled (a coverage map is not being generated). - fn add_coverage_counter_expression( - &mut self, - instance: Instance<'tcx>, - id: ExpressionId, - lhs: Operand, - op: Op, - rhs: Operand, - region: Option, - ) -> bool { - if let Some(coverage_context) = self.coverage_context() { - debug!( - "adding counter expression to coverage_map: instance={:?}, id={:?}, {:?} {:?} {:?}; \ - region: {:?}", - instance, id, lhs, op, rhs, region, - ); - let mut coverage_map = coverage_context.function_coverage_map.borrow_mut(); - coverage_map - .entry(instance) - .or_insert_with(|| FunctionCoverage::new(self.tcx, instance)) - .add_counter_expression(id, lhs, op, rhs, region); - true - } else { - false - } - } - - /// Returns true if the region was added to the coverage map; false if `-C instrument-coverage` - /// is not enabled (a coverage map is not being generated). - fn add_coverage_unreachable(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool { - if let Some(coverage_context) = self.coverage_context() { - debug!( - "adding unreachable code to coverage_map: instance={:?}, at {:?}", - instance, region, - ); - let mut coverage_map = coverage_context.function_coverage_map.borrow_mut(); - coverage_map - .entry(instance) - .or_insert_with(|| FunctionCoverage::new(self.tcx, instance)) - .add_unreachable_region(region); - true - } else { - false - } - } -} - fn declare_unused_fn<'tcx>(cx: &CodegenCx<'_, 'tcx>, def_id: DefId) -> Instance<'tcx> { let tcx = cx.tcx; From 74e5fef12dda59d3700b27dcf5b055e38047d40a Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Wed, 23 Aug 2023 18:57:35 +0200 Subject: [PATCH 10/11] Move Coverage Regions / Expressions to a side table Instead of encoding `CodeRegion`s and `CoverageExpression`s directly in a MIR `Coverage` statement, this moves this metadata to a side table. The `Coverage` statement is now only used to inject physical counters during codegen. --- .../src/coverageinfo/map_data.rs | 148 ++++++------------ .../src/coverageinfo/mapgen.rs | 26 ++- .../src/coverageinfo/mod.rs | 95 ++++------- compiler/rustc_middle/src/mir/coverage.rs | 92 ++++++----- compiler/rustc_middle/src/mir/mod.rs | 12 +- compiler/rustc_middle/src/mir/syntax.rs | 14 +- .../rustc_mir_build/src/build/custom/mod.rs | 1 + .../src/coverage/counters.rs | 15 +- .../rustc_mir_transform/src/coverage/debug.rs | 6 - .../rustc_mir_transform/src/coverage/mod.rs | 133 ++++++++-------- .../rustc_mir_transform/src/coverage/query.rs | 119 ++------------ compiler/rustc_mir_transform/src/simplify.rs | 95 +---------- 12 files changed, 254 insertions(+), 502 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 942feb97dbbec..e69c6be1963d2 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -1,8 +1,9 @@ use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; use rustc_data_structures::fx::FxHashMap; +use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; -use rustc_middle::mir::coverage::{CodeRegion, CounterId, ExpressionId, Op, Operand}; +use rustc_middle::mir::coverage::{CounterId, ExpressionId, Op, Operand}; use rustc_middle::ty::Instance; use rustc_middle::ty::TyCtxt; @@ -11,7 +12,6 @@ pub struct Expression { lhs: Operand, op: Op, rhs: Operand, - region: Option, } /// Collects all of the coverage regions associated with (a) injected counters, (b) counter @@ -26,16 +26,14 @@ pub struct Expression { /// for a gap area is only used as the line execution count if there are no other regions on a /// line." #[derive(Debug)] -pub struct FunctionCoverage<'tcx> { - instance: Instance<'tcx>, +pub struct FunctionCoverage { source_hash: u64, is_used: bool, - counters: IndexVec>, + counters: BitSet, expressions: IndexVec>, - unreachable_regions: Vec, } -impl<'tcx> FunctionCoverage<'tcx> { +impl<'tcx> FunctionCoverage { /// Creates a new set of coverage data for a used (called) function. pub fn new(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { Self::create(tcx, instance, true) @@ -53,12 +51,10 @@ impl<'tcx> FunctionCoverage<'tcx> { instance, coverageinfo, is_used ); Self { - instance, source_hash: 0, // will be set with the first `add_counter()` is_used, - counters: IndexVec::from_elem_n(None, coverageinfo.num_counters as usize), + counters: BitSet::new_empty(coverageinfo.num_counters as usize), expressions: IndexVec::from_elem_n(None, coverageinfo.num_expressions as usize), - unreachable_regions: Vec::new(), } } @@ -67,21 +63,17 @@ impl<'tcx> FunctionCoverage<'tcx> { self.is_used } - /// Sets the function source hash value. If called multiple times for the same function, all - /// calls should have the same hash value. - pub fn set_function_source_hash(&mut self, source_hash: u64) { + /// Adds a Counter, along with setting the function source hash value. + /// If called multiple times for the same function, + /// all calls should have the same `source_hash` value. + pub fn add_counter(&mut self, source_hash: u64, id: CounterId) { if self.source_hash == 0 { self.source_hash = source_hash; } else { debug_assert_eq!(source_hash, self.source_hash); } - } - /// Adds a code region to be counted by an injected counter intrinsic. - pub fn add_counter(&mut self, id: CounterId, region: CodeRegion) { - if let Some(previous_region) = self.counters[id].replace(region.clone()) { - assert_eq!(previous_region, region, "add_counter: code region for id changed"); - } + self.counters.insert(id); } /// Both counters and "counter expressions" (or simply, "expressions") can be operands in other @@ -93,11 +85,10 @@ impl<'tcx> FunctionCoverage<'tcx> { lhs: Operand, op: Op, rhs: Operand, - region: Option, ) { debug!( - "add_counter_expression({:?}, lhs={:?}, op={:?}, rhs={:?} at {:?}", - expression_id, lhs, op, rhs, region + "add_counter_expression({:?}, lhs={:?}, op={:?}, rhs={:?}", + expression_id, lhs, op, rhs ); debug_assert!( expression_id.as_usize() < self.expressions.len(), @@ -107,25 +98,17 @@ impl<'tcx> FunctionCoverage<'tcx> { self.expressions.len(), self, ); - if let Some(previous_expression) = self.expressions[expression_id].replace(Expression { - lhs, - op, - rhs, - region: region.clone(), - }) { + if let Some(previous_expression) = + self.expressions[expression_id].replace(Expression { lhs, op, rhs }) + { assert_eq!( previous_expression, - Expression { lhs, op, rhs, region }, + Expression { lhs, op, rhs }, "add_counter_expression: expression for id changed" ); } } - /// Add a region that will be marked as "unreachable", with a constant "zero counter". - pub fn add_unreachable_region(&mut self, region: CodeRegion) { - self.unreachable_regions.push(region) - } - /// Perform some simplifications to make the final coverage mappings /// slightly smaller. pub(crate) fn simplify_expressions(&mut self) { @@ -149,8 +132,14 @@ impl<'tcx> FunctionCoverage<'tcx> { // If an operand refers to an expression that has been simplified, then // replace that operand with the simplified version. - let maybe_simplify_operand = |operand: &mut Operand| { - if let Operand::Expression(id) = &*operand { + let maybe_simplify_operand = |operand: &mut Operand| match operand { + Operand::Zero => {} + Operand::Counter(id) => { + if !self.counters.contains(*id) { + *operand = Operand::Zero; + } + } + Operand::Expression(id) => { if let Some(simplified) = simplified_expressions.get(id) { *operand = *simplified; } @@ -182,62 +171,42 @@ impl<'tcx> FunctionCoverage<'tcx> { /// This will further simplify any expression, "inlining" the left hand side operand /// if the right hand side is `Zero`. This is similar to `simplify_expressions` above, /// but works for an already referenced expression. - fn simplified_expression(&self, id: ExpressionId) -> Counter { - if let Some(expr) = &self.expressions[id] { - if expr.rhs == Operand::Zero { - return Counter::from_operand(expr.lhs); + pub fn simplified_operand(&self, operand: Operand) -> Counter { + let operand = match operand { + Operand::Zero => operand, + Operand::Counter(id) => { + if !self.counters.contains(id) { + Operand::Zero + } else { + operand + } } - if expr.lhs == Operand::Zero { - return Counter::from_operand(expr.rhs); + Operand::Expression(id) => { + if let Some(expr) = &self.expressions[id] { + if expr.rhs == Operand::Zero { + expr.lhs + } else if expr.lhs == Operand::Zero { + expr.rhs + } else { + operand + } + } else { + operand + } } - } - Counter::expression(id) - } + }; + Counter::from_operand(operand) + } /// Return the source hash, generated from the HIR node structure, and used to indicate whether /// or not the source code structure changed between different compilations. pub fn source_hash(&self) -> u64 { self.source_hash } - /// Generate an array of CounterExpressions, and an iterator over all `Counter`s and their - /// associated `Regions` (from which the LLVM-specific `CoverageMapGenerator` will create - /// `CounterMappingRegion`s. - pub fn get_expressions_and_counter_regions( - &self, - ) -> (Vec, impl Iterator) { - assert!( - self.source_hash != 0 || !self.is_used, - "No counters provided the source_hash for used function: {:?}", - self.instance - ); - - let counter_expressions = self.counter_expressions(); - // Expression IDs are indices into `self.expressions`, and on the LLVM - // side they will be treated as indices into `counter_expressions`, so - // the two vectors should correspond 1:1. - assert_eq!(self.expressions.len(), counter_expressions.len()); - - let counter_regions = self.counter_regions(); - let expression_regions = self.expression_regions(); - let unreachable_regions = self.unreachable_regions(); - - let counter_regions = - counter_regions.chain(expression_regions.into_iter().chain(unreachable_regions)); - (counter_expressions, counter_regions) - } - - fn counter_regions(&self) -> impl Iterator { - self.counters.iter_enumerated().filter_map(|(index, entry)| { - // Option::map() will return None to filter out missing counters. This may happen - // if, for example, a MIR-instrumented counter is removed during an optimization. - entry.as_ref().map(|region| (Counter::counter_value_reference(index), region)) - }) - } - /// Convert this function's coverage expression data into a form that can be /// passed through FFI to LLVM. - fn counter_expressions(&self) -> Vec { + pub fn counter_expressions(&self) -> Vec { // We know that LLVM will optimize out any unused expressions before // producing the final coverage map, so there's no need to do the same // thing on the Rust side unless we're confident we can do much better. @@ -264,21 +233,4 @@ impl<'tcx> FunctionCoverage<'tcx> { }) .collect::>() } - - fn expression_regions(&self) -> Vec<(Counter, &CodeRegion)> { - // Find all of the expression IDs that weren't optimized out AND have - // an attached code region, and return the corresponding mapping as a - // counter/region pair. - self.expressions - .iter_enumerated() - .filter_map(|(id, expression)| { - let code_region = expression.as_ref()?.region.as_ref()?; - Some((self.simplified_expression(id), code_region)) - }) - .collect::>() - } - - fn unreachable_regions(&self) -> impl Iterator { - self.unreachable_regions.iter().map(|region| (Counter::ZERO, region)) - } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index d90ac44621d83..4ff62b49b1b88 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -10,7 +10,7 @@ use rustc_hir::def_id::DefId; use rustc_llvm::RustString; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::mir::coverage::CodeRegion; +use rustc_middle::mir::coverage::{CodeRegion, CoverageExpression, CoverageRegionKind}; use rustc_middle::ty::TyCtxt; use rustc_span::Symbol; @@ -61,13 +61,33 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) { let mut function_data = Vec::new(); for (instance, mut function_coverage) in function_coverage_map { debug!("Generate function coverage for {}, {:?}", cx.codegen_unit.name(), instance); + + let mir_body = tcx.instance_mir(instance.def); + let Some(coverage_info) = mir_body.coverage_info.as_ref() else { continue }; + for CoverageExpression { id, lhs, op, rhs } in &coverage_info.expressions { + debug!( + "adding counter expression to coverage_map: instance={:?}, id={:?}, {:?} {:?} {:?}", + instance, id, lhs, op, rhs, + ); + function_coverage.add_counter_expression(*id, *lhs, *op, *rhs); + } function_coverage.simplify_expressions(); + let expressions = function_coverage.counter_expressions(); + + let counter_regions = coverage_info.regions.iter().map(|region| { + ( + match region.kind { + CoverageRegionKind::Code(operand) => { + function_coverage.simplified_operand(operand) + } + }, + ®ion.code_region, + ) + }); let mangled_function_name = tcx.symbol_name(instance).name; let source_hash = function_coverage.source_hash(); let is_used = function_coverage.is_used(); - let (expressions, counter_regions) = - function_coverage.get_expressions_and_counter_regions(); let coverage_mapping_buffer = llvm::build_byte_buffer(|coverage_mapping_buffer| { mapgen.write_coverage_mapping(expressions, counter_regions, coverage_mapping_buffer); diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index c70cb670e96fb..d3ee5e8cce1cf 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -16,7 +16,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_llvm::RustString; use rustc_middle::bug; -use rustc_middle::mir::coverage::{CounterId, CoverageKind}; +use rustc_middle::mir::coverage::CounterId; use rustc_middle::mir::Coverage; use rustc_middle::ty; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; @@ -37,7 +37,7 @@ const VAR_ALIGN_BYTES: usize = 8; /// A context object for maintaining all state needed by the coverageinfo module. pub struct CrateCoverageContext<'ll, 'tcx> { /// Coverage data for each instrumented function identified by DefId. - pub(crate) function_coverage_map: RefCell, FunctionCoverage<'tcx>>>, + pub(crate) function_coverage_map: RefCell, FunctionCoverage>>, pub(crate) pgo_func_name_var_map: RefCell, &'ll llvm::Value>>, } @@ -49,7 +49,7 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { } } - pub fn take_function_coverage_map(&self) -> FxHashMap, FunctionCoverage<'tcx>> { + pub fn take_function_coverage_map(&self) -> FxHashMap, FunctionCoverage> { self.function_coverage_map.replace(FxHashMap::default()) } } @@ -105,63 +105,32 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { let bx = self; let Some(coverage_context) = bx.coverage_context() else { return }; - let mut coverage_map = coverage_context.function_coverage_map.borrow_mut(); - let func_coverage = coverage_map - .entry(instance) - .or_insert_with(|| FunctionCoverage::new(bx.tcx(), instance)); - - let Coverage { kind, code_region } = coverage.clone(); - match kind { - CoverageKind::Counter { function_source_hash, id } => { - debug!( - "ensuring function source hash is set for instance={:?}; function_source_hash={}", - instance, function_source_hash, - ); - func_coverage.set_function_source_hash(function_source_hash); - - if let Some(code_region) = code_region { - // Note: Some counters do not have code regions, but may still be referenced - // from expressions. In that case, don't add the counter to the coverage map, - // but do inject the counter intrinsic. - debug!( - "adding counter to coverage_map: instance={:?}, id={:?}, region={:?}", - instance, id, code_region, - ); - func_coverage.add_counter(id, code_region); - } - // We need to explicitly drop the `RefMut` before calling into `instrprof_increment`, - // as that needs an exclusive borrow. - drop(coverage_map); - - let coverageinfo = bx.tcx().coverageinfo(instance.def); - - let fn_name = bx.get_pgo_func_name_var(instance); - let hash = bx.const_u64(function_source_hash); - let num_counters = bx.const_u32(coverageinfo.num_counters); - let index = bx.const_u32(id.as_u32()); - debug!( - "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", - fn_name, hash, num_counters, index, - ); - bx.instrprof_increment(fn_name, hash, num_counters, index); - } - CoverageKind::Expression { id, lhs, op, rhs } => { - debug!( - "adding counter expression to coverage_map: instance={:?}, id={:?}, {:?} {:?} {:?}; region: {:?}", - instance, id, lhs, op, rhs, code_region, - ); - func_coverage.add_counter_expression(id, lhs, op, rhs, code_region); - } - CoverageKind::Unreachable => { - let code_region = - code_region.expect("unreachable regions always have code regions"); - debug!( - "adding unreachable code to coverage_map: instance={:?}, at {:?}", - instance, code_region, - ); - func_coverage.add_unreachable_region(code_region); - } + let Coverage { function_source_hash, id } = coverage.clone(); + + { + let mut coverage_map = coverage_context.function_coverage_map.borrow_mut(); + let func_coverage = coverage_map + .entry(instance) + .or_insert_with(|| FunctionCoverage::new(bx.tcx(), instance)); + + debug!( + "ensuring function source hash is set for instance={:?}; function_source_hash={}", + instance, function_source_hash, + ); + func_coverage.add_counter(function_source_hash, id); } + + let coverageinfo = bx.tcx().coverageinfo(instance.def); + + let fn_name = bx.get_pgo_func_name_var(instance); + let hash = bx.const_u64(function_source_hash); + let num_counters = bx.const_u32(coverageinfo.num_counters); + let index = bx.const_u32(id.as_u32()); + debug!( + "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", + fn_name, hash, num_counters, index, + ); + bx.instrprof_increment(fn_name, hash, num_counters, index); } } @@ -222,12 +191,12 @@ fn codegen_unused_fn_and_counter<'tcx>(cx: &CodegenCx<'_, 'tcx>, instance: Insta fn add_unused_function_coverage<'tcx>( cx: &CodegenCx<'_, 'tcx>, instance: Instance<'tcx>, - def_id: DefId, + _def_id: DefId, ) { let tcx = cx.tcx; - let mut function_coverage = FunctionCoverage::unused(tcx, instance); - for (index, &code_region) in tcx.covered_code_regions(def_id).iter().enumerate() { + let function_coverage = FunctionCoverage::unused(tcx, instance); + /*for (index, &code_region) in tcx.covered_code_regions(def_id).iter().enumerate() { if index == 0 { // Insert at least one real counter so the LLVM CoverageMappingReader will find expected // definitions. @@ -235,7 +204,7 @@ fn add_unused_function_coverage<'tcx>( } else { function_coverage.add_unreachable_region(code_region.clone()); } - } + }*/ if let Some(coverage_context) = cx.coverage_context() { coverage_context.function_coverage_map.borrow_mut().insert(instance, function_coverage); diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 9ef6739229118..b3660974609eb 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -1,5 +1,6 @@ //! Metadata from source code coverage analysis and instrumentation. +use rustc_index::IndexVec; use rustc_macros::HashStable; use rustc_span::Symbol; @@ -67,46 +68,6 @@ impl Debug for Operand { } } -#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] -pub enum CoverageKind { - Counter { - function_source_hash: u64, - /// ID of this counter within its enclosing function. - /// Expressions in the same function can refer to it as an operand. - id: CounterId, - }, - Expression { - /// ID of this coverage-counter expression within its enclosing function. - /// Other expressions in the same function can refer to it as an operand. - id: ExpressionId, - lhs: Operand, - op: Op, - rhs: Operand, - }, - Unreachable, -} - -impl Debug for CoverageKind { - fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { - use CoverageKind::*; - match self { - Counter { id, .. } => write!(fmt, "Counter({:?})", id.index()), - Expression { id, lhs, op, rhs } => write!( - fmt, - "Expression({:?}) = {:?} {} {:?}", - id.index(), - lhs, - match op { - Op::Add => "+", - Op::Subtract => "-", - }, - rhs, - ), - Unreachable => write!(fmt, "Unreachable"), - } - } -} - #[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq, PartialOrd, Ord)] #[derive(TypeFoldable, TypeVisitable)] pub struct CodeRegion { @@ -127,7 +88,7 @@ impl Debug for CodeRegion { } } -#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] #[derive(TypeFoldable, TypeVisitable)] pub enum Op { Subtract, @@ -143,3 +104,52 @@ impl Op { matches!(self, Self::Subtract) } } + +#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq)] +#[derive(TypeFoldable, TypeVisitable)] +pub struct CoverageExpression { + /// ID of this coverage-counter expression within its enclosing function. + /// Other expressions in the same function can refer to it as an operand. + pub id: ExpressionId, + pub lhs: Operand, + pub op: Op, + pub rhs: Operand, +} + +impl Debug for CoverageExpression { + fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { + let CoverageExpression { id, lhs, op, rhs } = self; + write!( + fmt, + "Expression({:?}) = {:?} {} {:?}", + id.index(), + lhs, + match op { + Op::Add => "+", + Op::Subtract => "-", + }, + rhs, + ) + } +} + +#[derive(Clone, Debug, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq)] +#[derive(TypeFoldable, TypeVisitable)] +pub enum CoverageRegionKind { + Code(Operand), +} + +#[derive(Clone, Debug, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq)] +#[derive(TypeFoldable, TypeVisitable)] +pub struct CoverageRegion { + pub kind: CoverageRegionKind, + pub code_region: CodeRegion, +} + +#[derive(Clone, Debug, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq)] +#[derive(TypeFoldable, TypeVisitable)] +pub struct CoverageInfo { + pub num_counters: u32, + pub expressions: IndexVec, + pub regions: Vec, +} diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 9ef3a1b30e498..7cc6e4003b1d9 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -243,6 +243,11 @@ pub struct Body<'tcx> { /// and used for debuginfo. Indexed by a `SourceScope`. pub source_scopes: IndexVec>, + /// This is metadata computed by the `-C instrument-coverage` option. + /// The metadata includes the code regions relevant for code coverage, as + /// well as intermediate expressions used for a regions counter. + pub coverage_info: Option>, + pub generator: Option>>, /// Declarations of locals. @@ -333,6 +338,7 @@ impl<'tcx> Body<'tcx> { source, basic_blocks: BasicBlocks::new(basic_blocks), source_scopes, + coverage_info: None, generator: generator_kind.map(|generator_kind| { Box::new(GeneratorInfo { yield_ty: None, @@ -368,6 +374,7 @@ impl<'tcx> Body<'tcx> { source: MirSource::item(CRATE_DEF_ID.to_def_id()), basic_blocks: BasicBlocks::new(basic_blocks), source_scopes: IndexVec::new(), + coverage_info: None, generator: None, local_decls: IndexVec::new(), user_type_annotations: IndexVec::new(), @@ -1474,10 +1481,9 @@ impl Debug for Statement<'_> { AscribeUserType(box (ref place, ref c_ty), ref variance) => { write!(fmt, "AscribeUserType({place:?}, {variance:?}, {c_ty:?})") } - Coverage(box self::Coverage { ref kind, code_region: Some(ref rgn) }) => { - write!(fmt, "Coverage::{kind:?} for {rgn:?}") + Coverage(box ref coverage) => { + write!(fmt, "Coverage({coverage:?})") } - Coverage(box ref coverage) => write!(fmt, "Coverage::{:?}", coverage.kind), Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"), ConstEvalCounter => write!(fmt, "ConstEvalCounter"), Nop => write!(fmt, "nop"), diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index e91e822f915ab..c82565ccfc754 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -5,7 +5,7 @@ use super::{BasicBlock, Constant, Local, SwitchTargets, UserTypeProjection}; -use crate::mir::coverage::{CodeRegion, CoverageKind}; +use crate::mir::coverage::CounterId; use crate::traits::Reveal; use crate::ty::adjustment::PointerCoercion; use crate::ty::GenericArgsRef; @@ -359,11 +359,9 @@ pub enum StatementKind<'tcx> { /// Disallowed after drop elaboration. AscribeUserType(Box<(Place<'tcx>, UserTypeProjection)>, ty::Variance), - /// Marks the start of a "coverage region", injected with '-Cinstrument-coverage'. A - /// `Coverage` statement carries metadata about the coverage region, used to inject a coverage - /// map into the binary. If `Coverage::kind` is a `Counter`, the statement also generates - /// executable code, to increment a counter variable at runtime, each time the code region is - /// executed. + /// A coverage counter injected with '-Cinstrument-coverage'. + /// This statement generates executable code to increment a counter variable at runtime, + /// each time the code region is executed. Coverage(Box), /// Denotes a call to an intrinsic that does not require an unwind path and always returns. @@ -522,8 +520,8 @@ pub enum FakeReadCause { #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] #[derive(TypeFoldable, TypeVisitable)] pub struct Coverage { - pub kind: CoverageKind, - pub code_region: Option, + pub function_source_hash: u64, + pub id: CounterId, } #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index e5c2cc6c7bbce..237623d5160e0 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -48,6 +48,7 @@ pub(super) fn build_custom_mir<'tcx>( source: MirSource::item(did), phase: MirPhase::Built, source_scopes: IndexVec::new(), + coverage_info: None, generator: None, local_decls: IndexVec::new(), user_type_annotations: IndexVec::new(), diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 3d442e5dca9f9..9309f90bba7da 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -59,8 +59,8 @@ impl Debug for BcbCounter { /// Generates and stores coverage counter and coverage expression information /// associated with nodes/edges in the BCB graph. pub(super) struct CoverageCounters { - next_counter_id: CounterId, - next_expression_id: ExpressionId, + pub(super) next_counter_id: CounterId, + pub(super) next_expression_id: ExpressionId, /// Coverage counters/expressions that are associated with individual BCBs. bcb_counters: IndexVec>, @@ -142,17 +142,6 @@ impl CoverageCounters { expression } - pub fn make_identity_counter(&mut self, counter_operand: Operand) -> BcbCounter { - let some_debug_block_label = if self.debug_counters.is_enabled() { - self.debug_counters.some_block_label(counter_operand).cloned() - } else { - None - }; - self.make_expression(counter_operand, Op::Add, Operand::Zero, || { - some_debug_block_label.clone() - }) - } - /// Counter IDs start from one and go up. fn next_counter(&mut self) -> CounterId { let next = self.next_counter_id; diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs index af616c498fd3a..90141d497cd9c 100644 --- a/compiler/rustc_mir_transform/src/coverage/debug.rs +++ b/compiler/rustc_mir_transform/src/coverage/debug.rs @@ -285,12 +285,6 @@ impl DebugCounters { } } - pub fn some_block_label(&self, operand: Operand) -> Option<&String> { - self.some_counters.as_ref().and_then(|counters| { - counters.get(&operand).and_then(|debug_counter| debug_counter.some_block_label.as_ref()) - }) - } - pub fn format_counter(&self, counter_kind: &BcbCounter) -> String { match *counter_kind { BcbCounter::Counter { .. } => { diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 8c9eae508b4ae..d2872d28b9541 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -207,6 +207,16 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { let result = self .coverage_counters .make_bcb_counters(&mut self.basic_coverage_blocks, &coverage_spans); + let num_counters = self.coverage_counters.next_counter_id.as_u32(); + let num_expressions = self.coverage_counters.next_expression_id.as_usize(); + let mut coverage_info = CoverageInfo { + num_counters, + expressions: IndexVec::from_fn_n( + |id| CoverageExpression { id, lhs: Operand::Zero, op: Op::Add, rhs: Operand::Zero }, + num_expressions, + ), + regions: vec![], + }; if let Ok(()) = result { // If debugging, add any intermediate expressions (which are not associated with any @@ -231,6 +241,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { coverage_spans, &mut graphviz_data, &mut debug_used_expressions, + &mut coverage_info, ); //////////////////////////////////////////////////// @@ -239,7 +250,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { // to ensure `BasicCoverageBlock` counters that other `Expression`s may depend on // are in fact counted, even though they don't directly contribute to counting // their own independent code region's coverage. - self.inject_indirect_counters(&mut graphviz_data, &mut debug_used_expressions); + self.inject_indirect_counters( + &mut graphviz_data, + &mut debug_used_expressions, + &mut coverage_info, + ); // Intermediate expressions will be injected as the final step, after generating // debug output, if any. @@ -273,11 +288,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { //////////////////////////////////////////////////// // Finally, inject the intermediate expressions collected along the way. for intermediate_expression in &self.coverage_counters.intermediate_expressions { - inject_intermediate_expression( - self.mir_body, - self.make_mir_coverage_kind(intermediate_expression), - ); + if let BcbCounter::Expression { id, lhs, op, rhs } = intermediate_expression.clone() { + coverage_info.expressions[id] = CoverageExpression { id, lhs, op, rhs } + } } + self.mir_body.coverage_info = Some(Box::new(coverage_info)); } /// Inject a counter for each `CoverageSpan`. There can be multiple `CoverageSpan`s for a given @@ -293,36 +308,56 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { coverage_spans: Vec, graphviz_data: &mut debug::GraphvizData, debug_used_expressions: &mut debug::UsedExpressions, + coverage_info: &mut CoverageInfo, ) { let tcx = self.tcx; let source_map = tcx.sess.source_map(); let body_span = self.body_span; let file_name = Symbol::intern(&self.source_file.name.prefer_remapped().to_string_lossy()); - let mut bcb_counters = IndexVec::from_elem_n(None, self.basic_coverage_blocks.num_nodes()); + let mut bcb_counters = + IndexVec::from_elem_n(None::, self.basic_coverage_blocks.num_nodes()); for covspan in coverage_spans { let bcb = covspan.bcb; let span = covspan.span; - let counter_kind = if let Some(&counter_operand) = bcb_counters[bcb].as_ref() { - self.coverage_counters.make_identity_counter(counter_operand) - } else if let Some(counter_kind) = self.coverage_counters.take_bcb_counter(bcb) { - bcb_counters[bcb] = Some(counter_kind.as_operand()); - debug_used_expressions.add_expression_operands(&counter_kind); - counter_kind - } else { - bug!("Every BasicCoverageBlock should have a Counter or Expression"); - }; + let (counter_kind, was_injected) = + if let Some(counter_kind) = bcb_counters[bcb].as_ref() { + (counter_kind.clone(), true) + } else if let Some(counter_kind) = self.coverage_counters.take_bcb_counter(bcb) { + bcb_counters[bcb] = Some(counter_kind.clone()); + debug_used_expressions.add_expression_operands(&counter_kind); + (counter_kind, false) + } else { + bug!("Every BasicCoverageBlock should have a Counter or Expression"); + }; graphviz_data.add_bcb_coverage_span_with_counter(bcb, &covspan, &counter_kind); let code_region = make_code_region(source_map, file_name, &self.source_file, span, body_span); - inject_statement( - self.mir_body, - self.make_mir_coverage_kind(&counter_kind), - self.bcb_leader_bb(bcb), - Some(code_region), - ); + match counter_kind { + BcbCounter::Counter { id } => { + if !was_injected { + inject_statement( + self.mir_body, + self.bcb_leader_bb(bcb), + self.function_source_hash, + id, + ); + } + coverage_info.regions.push(CoverageRegion { + kind: CoverageRegionKind::Code(Operand::Counter(id)), + code_region, + }); + } + BcbCounter::Expression { id, lhs, op, rhs } => { + coverage_info.expressions[id] = CoverageExpression { id, lhs, op, rhs }; + coverage_info.regions.push(CoverageRegion { + kind: CoverageRegionKind::Code(Operand::Expression(id)), + code_region, + }); + } + } } } @@ -338,6 +373,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { &mut self, graphviz_data: &mut debug::GraphvizData, debug_used_expressions: &mut debug::UsedExpressions, + coverage_info: &mut CoverageInfo, ) { let mut bcb_counters_without_direct_coverage_spans = Vec::new(); for (target_bcb, counter_kind) in self.coverage_counters.drain_bcb_counters() { @@ -367,7 +403,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { ); match counter_kind { - BcbCounter::Counter { .. } => { + BcbCounter::Counter { id } => { let inject_to_bb = if let Some(from_bcb) = edge_from_bcb { // The MIR edge starts `from_bb` (the outgoing / last BasicBlock in // `from_bcb`) and ends at `to_bb` (the incoming / first BasicBlock in the @@ -400,17 +436,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { target_bb }; - inject_statement( - self.mir_body, - self.make_mir_coverage_kind(&counter_kind), - inject_to_bb, - None, - ); + inject_statement(self.mir_body, inject_to_bb, self.function_source_hash, id); + } + BcbCounter::Expression { id, lhs, op, rhs } => { + coverage_info.expressions[id] = CoverageExpression { id, lhs, op, rhs } } - BcbCounter::Expression { .. } => inject_intermediate_expression( - self.mir_body, - self.make_mir_coverage_kind(&counter_kind), - ), } } } @@ -434,17 +464,6 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { fn format_counter(&self, counter_kind: &BcbCounter) -> String { self.coverage_counters.debug_counters.format_counter(counter_kind) } - - fn make_mir_coverage_kind(&self, counter_kind: &BcbCounter) -> CoverageKind { - match *counter_kind { - BcbCounter::Counter { id } => { - CoverageKind::Counter { function_source_hash: self.function_source_hash, id } - } - BcbCounter::Expression { id, lhs, op, rhs } => { - CoverageKind::Expression { id, lhs, op, rhs } - } - } - } } fn inject_edge_counter_basic_block( @@ -472,40 +491,20 @@ fn inject_edge_counter_basic_block( fn inject_statement( mir_body: &mut mir::Body<'_>, - counter_kind: CoverageKind, bb: BasicBlock, - some_code_region: Option, + function_source_hash: u64, + id: CounterId, ) { - debug!( - " injecting statement {:?} for {:?} at code region: {:?}", - counter_kind, bb, some_code_region - ); + debug!(" injecting counter statement {id:?} for {bb:?}",); let data = &mut mir_body[bb]; let source_info = data.terminator().source_info; let statement = Statement { source_info, - kind: StatementKind::Coverage(Box::new(Coverage { - kind: counter_kind, - code_region: some_code_region, - })), + kind: StatementKind::Coverage(Box::new(Coverage { function_source_hash, id })), }; data.statements.insert(0, statement); } -// Non-code expressions are injected into the coverage map, without generating executable code. -fn inject_intermediate_expression(mir_body: &mut mir::Body<'_>, expression: CoverageKind) { - debug_assert!(matches!(expression, CoverageKind::Expression { .. })); - debug!(" injecting non-code expression {:?}", expression); - let inject_in_bb = mir::START_BLOCK; - let data = &mut mir_body[inject_in_bb]; - let source_info = data.terminator().source_info; - let statement = Statement { - source_info, - kind: StatementKind::Coverage(Box::new(Coverage { kind: expression, code_region: None })), - }; - data.statements.push(statement); -} - /// Convert the Span into its file name, start line and column, and end line and column fn make_code_region( source_map: &SourceMap, diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index aa205655f9dab..42e7a244e5991 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -1,7 +1,5 @@ -use super::*; - use rustc_middle::mir::coverage::*; -use rustc_middle::mir::{self, Body, Coverage, CoverageInfo}; +use rustc_middle::mir::{self, CoverageInfo}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefId; @@ -24,117 +22,24 @@ pub(crate) fn provide(providers: &mut Providers) { /// /// MIR optimization may split and duplicate some BasicBlock sequences, or optimize out some code /// including injected counters. (It is OK if some counters are optimized out, but those counters -/// are still included in the total `num_counters` or `num_expressions`.) Simply counting the -/// calls may not work; but computing the number of counters or expressions by adding `1` to the -/// highest ID (for a given instrumented function) is valid. -/// -/// This visitor runs twice, first with `add_missing_operands` set to `false`, to find the maximum -/// counter ID and maximum expression ID based on their enum variant `id` fields; then, as a -/// safeguard, with `add_missing_operands` set to `true`, to find any other counter or expression -/// IDs referenced by expression operands, if not already seen. -/// -/// Ideally, each operand ID in a MIR `CoverageKind::Expression` will have a separate MIR `Coverage` -/// statement for the `Counter` or `Expression` with the referenced ID. but since current or future -/// MIR optimizations can theoretically optimize out segments of a MIR, it may not be possible to -/// guarantee this, so the second pass ensures the `CoverageInfo` counts include all referenced IDs. -struct CoverageVisitor { - info: CoverageInfo, - add_missing_operands: bool, -} - -impl CoverageVisitor { - /// Updates `num_counters` to the maximum encountered counter ID plus 1. - #[inline(always)] - fn update_num_counters(&mut self, counter_id: CounterId) { - let counter_id = counter_id.as_u32(); - self.info.num_counters = std::cmp::max(self.info.num_counters, counter_id + 1); - } - - /// Updates `num_expressions` to the maximum encountered expression ID plus 1. - #[inline(always)] - fn update_num_expressions(&mut self, expression_id: ExpressionId) { - let expression_id = expression_id.as_u32(); - self.info.num_expressions = std::cmp::max(self.info.num_expressions, expression_id + 1); - } - - fn update_from_expression_operand(&mut self, operand: Operand) { - match operand { - Operand::Counter(id) => self.update_num_counters(id), - Operand::Expression(id) => self.update_num_expressions(id), - Operand::Zero => {} - } - } - - fn visit_body(&mut self, body: &Body<'_>) { - for bb_data in body.basic_blocks.iter() { - for statement in bb_data.statements.iter() { - if let StatementKind::Coverage(box ref coverage) = statement.kind { - if is_inlined(body, statement) { - continue; - } - self.visit_coverage(coverage); - } - } - } - } - - fn visit_coverage(&mut self, coverage: &Coverage) { - if self.add_missing_operands { - match coverage.kind { - CoverageKind::Expression { lhs, rhs, .. } => { - self.update_from_expression_operand(lhs); - self.update_from_expression_operand(rhs); - } - _ => {} - } - } else { - match coverage.kind { - CoverageKind::Counter { id, .. } => self.update_num_counters(id), - CoverageKind::Expression { id, .. } => self.update_num_expressions(id), - _ => {} - } - } - } -} - +/// are still included in the total `num_counters` or `num_expressions`.) fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) -> CoverageInfo { let mir_body = tcx.instance_mir(instance_def); - let mut coverage_visitor = CoverageVisitor { - info: CoverageInfo { num_counters: 0, num_expressions: 0 }, - add_missing_operands: false, - }; - - coverage_visitor.visit_body(mir_body); - - coverage_visitor.add_missing_operands = true; - coverage_visitor.visit_body(mir_body); - - coverage_visitor.info + if let Some(info) = &mir_body.coverage_info { + CoverageInfo { + num_counters: info.num_counters, + num_expressions: info.expressions.len() as u32, + } + } else { + CoverageInfo { num_counters: 0, num_expressions: 0 } + } } fn covered_code_regions(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<&CodeRegion> { let body = mir_body(tcx, def_id); - body.basic_blocks - .iter() - .flat_map(|data| { - data.statements.iter().filter_map(|statement| match statement.kind { - StatementKind::Coverage(box ref coverage) => { - if is_inlined(body, statement) { - None - } else { - coverage.code_region.as_ref() // may be None - } - } - _ => None, - }) - }) - .collect() -} - -fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool { - let scope_data = &body.source_scopes[statement.source_info.scope]; - scope_data.inlined.is_some() || scope_data.inlined_parent_scope.is_some() + let Some(info) = body.coverage_info.as_ref() else { return vec![] }; + info.regions.iter().map(|region| ®ion.code_region).collect() } /// This function ensures we obtain the correct MIR for the given item irrespective of diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index b7a51cfd61966..b647c4658ddba 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -28,9 +28,8 @@ //! return. use crate::MirPass; -use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::FxIndexSet; use rustc_index::{Idx, IndexSlice, IndexVec}; -use rustc_middle::mir::coverage::*; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -336,7 +335,7 @@ pub fn remove_duplicate_unreachable_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut B } } -pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +pub fn remove_dead_blocks<'tcx>(_tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let reachable = traversal::reachable_as_bitset(body); let num_blocks = body.basic_blocks.len(); if num_blocks == reachable.count() { @@ -344,7 +343,6 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { } let basic_blocks = body.basic_blocks.as_mut(); - let source_scopes = &body.source_scopes; let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect(); let mut used_blocks = 0; for alive_index in reachable.iter() { @@ -358,10 +356,6 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { used_blocks += 1; } - if tcx.sess.instrument_coverage() { - save_unreachable_coverage(basic_blocks, source_scopes, used_blocks); - } - basic_blocks.raw.truncate(used_blocks); for block in basic_blocks { @@ -371,91 +365,6 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { } } -/// Some MIR transforms can determine at compile time that a sequences of -/// statements will never be executed, so they can be dropped from the MIR. -/// For example, an `if` or `else` block that is guaranteed to never be executed -/// because its condition can be evaluated at compile time, such as by const -/// evaluation: `if false { ... }`. -/// -/// Those statements are bypassed by redirecting paths in the CFG around the -/// `dead blocks`; but with `-C instrument-coverage`, the dead blocks usually -/// include `Coverage` statements representing the Rust source code regions to -/// be counted at runtime. Without these `Coverage` statements, the regions are -/// lost, and the Rust source code will show no coverage information. -/// -/// What we want to show in a coverage report is the dead code with coverage -/// counts of `0`. To do this, we need to save the code regions, by injecting -/// `Unreachable` coverage statements. These are non-executable statements whose -/// code regions are still recorded in the coverage map, representing regions -/// with `0` executions. -/// -/// If there are no live `Counter` `Coverage` statements remaining, we remove -/// `Coverage` statements along with the dead blocks. Since at least one -/// counter per function is required by LLVM (and necessary, to add the -/// `function_hash` to the counter's call to the LLVM intrinsic -/// `instrprof.increment()`). -/// -/// The `generator::StateTransform` MIR pass and MIR inlining can create -/// atypical conditions, where all live `Counter`s are dropped from the MIR. -/// -/// With MIR inlining we can have coverage counters belonging to different -/// instances in a single body, so the strategy described above is applied to -/// coverage counters from each instance individually. -fn save_unreachable_coverage( - basic_blocks: &mut IndexSlice>, - source_scopes: &IndexSlice>, - first_dead_block: usize, -) { - // Identify instances that still have some live coverage counters left. - let mut live = FxHashSet::default(); - for basic_block in &basic_blocks.raw[0..first_dead_block] { - for statement in &basic_block.statements { - let StatementKind::Coverage(coverage) = &statement.kind else { continue }; - let CoverageKind::Counter { .. } = coverage.kind else { continue }; - let instance = statement.source_info.scope.inlined_instance(source_scopes); - live.insert(instance); - } - } - - for block in &mut basic_blocks.raw[..first_dead_block] { - for statement in &mut block.statements { - let StatementKind::Coverage(_) = &statement.kind else { continue }; - let instance = statement.source_info.scope.inlined_instance(source_scopes); - if !live.contains(&instance) { - statement.make_nop(); - } - } - } - - if live.is_empty() { - return; - } - - // Retain coverage for instances that still have some live counters left. - let mut retained_coverage = Vec::new(); - for dead_block in &basic_blocks.raw[first_dead_block..] { - for statement in &dead_block.statements { - let StatementKind::Coverage(coverage) = &statement.kind else { continue }; - let Some(code_region) = &coverage.code_region else { continue }; - let instance = statement.source_info.scope.inlined_instance(source_scopes); - if live.contains(&instance) { - retained_coverage.push((statement.source_info, code_region.clone())); - } - } - } - - let start_block = &mut basic_blocks[START_BLOCK]; - start_block.statements.extend(retained_coverage.into_iter().map( - |(source_info, code_region)| Statement { - source_info, - kind: StatementKind::Coverage(Box::new(Coverage { - kind: CoverageKind::Unreachable, - code_region: Some(code_region), - })), - }, - )); -} - pub enum SimplifyLocals { BeforeConstProp, Final, From e0bade399b6e0a248d0b12500a8ada09edf86cea Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Thu, 24 Aug 2023 12:43:45 +0200 Subject: [PATCH 11/11] bless coverage map tests --- tests/coverage-map/status-quo/async2.cov-map | 12 +- .../status-quo/conditions.cov-map | 314 +++++++++++------- .../status-quo/drop_trait.cov-map | 12 +- .../coverage-map/status-quo/generics.cov-map | 12 +- .../status-quo/loops_branches.cov-map | 209 +++++------- tests/coverage-map/status-quo/unused.cov-map | 16 +- 6 files changed, 312 insertions(+), 263 deletions(-) diff --git a/tests/coverage-map/status-quo/async2.cov-map b/tests/coverage-map/status-quo/async2.cov-map index 773daa4feaaa1..5be7c32b69db9 100644 --- a/tests/coverage-map/status-quo/async2.cov-map +++ b/tests/coverage-map/status-quo/async2.cov-map @@ -118,13 +118,17 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 35, 1) to (start + 7, 2) Function name: async2::non_async_func -Raw bytes (24): 0x[01, 01, 00, 04, 01, 09, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 05, 01, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 09, 01, 03, 09, 05, 03, 0a, 02, 06, 02, 02, 06, 00, 07, 07, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 0 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 9, 1) to (start + 3, 9) - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) -- Code(Zero) at (prev + 2, 6) to (start + 0, 7) -- Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) diff --git a/tests/coverage-map/status-quo/conditions.cov-map b/tests/coverage-map/status-quo/conditions.cov-map index 844a625cf4723..7d1392a2c13fe 100644 --- a/tests/coverage-map/status-quo/conditions.cov-map +++ b/tests/coverage-map/status-quo/conditions.cov-map @@ -1,163 +1,253 @@ Function name: conditions::main -Raw bytes (503): 0x[01, 01, 3c, 09, 13, 2d, 31, 05, 09, 0d, 39, 2d, 31, ee, 01, 0d, 05, 09, 35, 3d, 32, 29, 35, 3d, 2e, 51, 32, 29, 35, 3d, 45, 49, 3d, 3f, 45, 49, 55, 59, 56, 25, 55, 59, 52, 79, 56, 25, 55, 59, 5d, 61, 59, 63, 5d, 61, 6d, c7, 01, 71, 75, 65, 6d, 82, 01, 21, 65, 6d, 7e, 7d, 82, 01, 21, 65, 6d, 71, 75, 11, d7, 01, 15, 19, 6d, c7, 01, 71, 75, c3, 01, 11, 6d, c7, 01, 71, 75, be, 01, 1d, c3, 01, 11, 6d, c7, 01, 71, 75, ba, 01, 89, 01, be, 01, 1d, c3, 01, 11, 6d, c7, 01, 71, 75, 15, 19, d3, 01, db, 01, 11, d7, 01, 15, 19, df, 01, ea, 01, e3, 01, e7, 01, 1d, 21, 25, 29, ee, 01, 0d, 05, 09, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 03, 09, 00, 0a, 05, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, ee, 01, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 0e, 00, 1d, 00, 2a, 41, 00, 2e, 00, 3c, 2d, 00, 3d, 02, 0a, 31, 02, 0a, 00, 0b, 13, 01, 09, 01, 12, ea, 01, 03, 09, 00, 0f, 03, 03, 09, 01, 0c, 35, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 35, 02, 08, 00, 15, 3d, 00, 16, 02, 06, 32, 02, 0f, 00, 1c, 2e, 01, 0c, 00, 19, 2a, 00, 1d, 00, 2a, 69, 00, 2e, 00, 3c, 45, 00, 3d, 02, 0a, 49, 02, 0a, 00, 0b, 3f, 01, 09, 00, 17, 29, 02, 09, 00, 0f, 3b, 03, 08, 00, 0c, 4d, 01, 0d, 01, 10, 55, 01, 11, 02, 0a, 00, 02, 0a, 00, 0b, 55, 02, 0c, 00, 19, 59, 00, 1a, 02, 0a, 56, 03, 11, 00, 1e, 52, 01, 10, 00, 1d, 4e, 00, 21, 00, 2e, 81, 01, 00, 32, 00, 40, 5d, 00, 41, 02, 0e, 61, 02, 0e, 00, 0f, 63, 01, 0d, 00, 1b, 25, 02, 0d, 00, 13, 00, 02, 06, 00, 07, 5f, 03, 09, 01, 0c, 65, 01, 0d, 02, 06, 00, 02, 06, 00, 07, c3, 01, 02, 09, 00, 0a, 65, 00, 10, 00, 1d, 6d, 00, 1e, 02, 06, 82, 01, 02, 0f, 00, 1c, 7e, 01, 0c, 00, 19, 7a, 00, 1d, 00, 2a, 85, 01, 00, 2e, 00, 3c, 71, 00, 3d, 02, 0a, 75, 02, 0a, 00, 0b, c7, 01, 01, 09, 00, 17, 21, 02, 0d, 02, 0f, d3, 01, 05, 09, 00, 0a, c3, 01, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, be, 01, 02, 0f, 00, 1c, ba, 01, 01, 0c, 00, 19, b6, 01, 00, 1d, 00, 2a, 8d, 01, 00, 2e, 00, 3c, 15, 00, 3d, 02, 0a, 19, 02, 0a, 00, 0b, d7, 01, 01, 09, 00, 17, 1d, 02, 09, 00, 0f, cf, 01, 02, 01, 00, 02] +Raw bytes (769): 0x[01, 01, 8d, 01, 01, 05, 09, 97, 01, 2d, 31, 05, 02, b3, 04, 09, 05, 02, 0d, 39, 2d, 31, ae, 04, 0d, b3, 04, 09, 05, 02, 09, 97, 01, 2d, 31, 93, 01, 35, 09, 97, 01, 2d, 31, 35, 8e, 01, 93, 01, 35, 09, 97, 01, 2d, 31, 8b, 01, 3d, 35, 8e, 01, 93, 01, 35, 09, 97, 01, 2d, 31, 86, 01, 29, 8b, 01, 3d, 35, 8e, 01, 93, 01, 35, 09, 97, 01, 2d, 31, 82, 01, 51, 86, 01, 29, 8b, 01, 3d, 35, 8e, 01, 93, 01, 35, 09, 97, 01, 2d, 31, 45, 49, 3d, c3, 03, 45, 49, 4d, 55, 55, de, 01, 4d, 55, db, 01, 59, 55, de, 01, 4d, 55, d6, 01, 25, db, 01, 59, 55, de, 01, 4d, 55, d2, 01, 79, d6, 01, 25, db, 01, 59, 55, de, 01, 4d, 55, 5d, 61, bf, 03, 4d, 3d, c3, 03, 45, 49, b3, 03, ba, 03, 59, b7, 03, 5d, 61, bf, 03, 4d, 3d, c3, 03, 45, 49, af, 03, 65, b3, 03, ba, 03, 59, b7, 03, 5d, 61, bf, 03, 4d, 3d, c3, 03, 45, 49, 6d, 87, 04, 71, 75, 65, aa, 03, af, 03, 65, b3, 03, ba, 03, 59, b7, 03, 5d, 61, bf, 03, 4d, 3d, c3, 03, 45, 49, a7, 03, 6d, 65, aa, 03, af, 03, 65, b3, 03, ba, 03, 59, b7, 03, 5d, 61, bf, 03, 4d, 3d, c3, 03, 45, 49, a2, 03, 21, a7, 03, 6d, 65, aa, 03, af, 03, 65, b3, 03, ba, 03, 59, b7, 03, 5d, 61, bf, 03, 4d, 3d, c3, 03, 45, 49, 9e, 03, 7d, a2, 03, 21, a7, 03, 6d, 65, aa, 03, af, 03, 65, b3, 03, ba, 03, 59, b7, 03, 5d, 61, bf, 03, 4d, 3d, c3, 03, 45, 49, 71, 75, 11, 97, 04, 15, 19, 6d, 87, 04, 71, 75, 83, 04, 11, 6d, 87, 04, 71, 75, fe, 03, 1d, 83, 04, 11, 6d, 87, 04, 71, 75, fa, 03, 89, 01, fe, 03, 1d, 83, 04, 11, 6d, 87, 04, 71, 75, 15, 19, 93, 04, 9b, 04, 11, 97, 04, 15, 19, 9f, 04, aa, 04, a3, 04, a7, 04, 1d, 21, 25, 29, ae, 04, 0d, b3, 04, 09, 05, 02, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 02, 02, 06, 00, 07, 93, 01, 03, 09, 00, 0a, b3, 04, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, ae, 04, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 1a, 00, 1d, 00, 2a, 41, 00, 2e, 00, 3c, 2d, 00, 3d, 02, 0a, 31, 02, 0a, 00, 0b, 97, 01, 01, 09, 01, 12, aa, 04, 03, 09, 00, 0f, 93, 01, 03, 09, 01, 0c, 35, 01, 0d, 02, 06, 8e, 01, 02, 06, 00, 07, 8b, 01, 02, 08, 00, 15, 3d, 00, 16, 02, 06, 86, 01, 02, 0f, 00, 1c, 82, 01, 01, 0c, 00, 19, 7e, 00, 1d, 00, 2a, 69, 00, 2e, 00, 3c, 45, 00, 3d, 02, 0a, 49, 02, 0a, 00, 0b, c3, 03, 01, 09, 00, 17, 29, 02, 09, 00, 0f, bf, 03, 03, 08, 00, 0c, 4d, 01, 0d, 01, 10, 55, 01, 11, 02, 0a, de, 01, 02, 0a, 00, 0b, db, 01, 02, 0c, 00, 19, 59, 00, 1a, 02, 0a, d6, 01, 03, 11, 00, 1e, d2, 01, 01, 10, 00, 1d, ce, 01, 00, 21, 00, 2e, 81, 01, 00, 32, 00, 40, 5d, 00, 41, 02, 0e, 61, 02, 0e, 00, 0f, b7, 03, 01, 0d, 00, 1b, 25, 02, 0d, 00, 13, ba, 03, 02, 06, 00, 07, af, 03, 03, 09, 01, 0c, 65, 01, 0d, 02, 06, aa, 03, 02, 06, 00, 07, 83, 04, 02, 09, 00, 0a, a7, 03, 00, 10, 00, 1d, 6d, 00, 1e, 02, 06, a2, 03, 02, 0f, 00, 1c, 9e, 03, 01, 0c, 00, 19, 9a, 03, 00, 1d, 00, 2a, 85, 01, 00, 2e, 00, 3c, 71, 00, 3d, 02, 0a, 75, 02, 0a, 00, 0b, 87, 04, 01, 09, 00, 17, 21, 02, 0d, 02, 0f, 93, 04, 05, 09, 00, 0a, 83, 04, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, fe, 03, 02, 0f, 00, 1c, fa, 03, 01, 0c, 00, 19, f6, 03, 00, 1d, 00, 2a, 8d, 01, 00, 2e, 00, 3c, 15, 00, 3d, 02, 0a, 19, 02, 0a, 00, 0b, 97, 04, 01, 09, 00, 17, 1d, 02, 09, 00, 0f, 8f, 04, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 60 -- expression 0 operands: lhs = Counter(2), rhs = Expression(4, Add) -- expression 1 operands: lhs = Counter(11), rhs = Counter(12) -- expression 2 operands: lhs = Counter(1), rhs = Counter(2) -- expression 3 operands: lhs = Counter(3), rhs = Counter(14) -- expression 4 operands: lhs = Counter(11), rhs = Counter(12) -- expression 5 operands: lhs = Expression(59, Sub), rhs = Counter(3) -- expression 6 operands: lhs = Counter(1), rhs = Counter(2) -- expression 7 operands: lhs = Counter(13), rhs = Counter(15) -- expression 8 operands: lhs = Expression(12, Sub), rhs = Counter(10) -- expression 9 operands: lhs = Counter(13), rhs = Counter(15) -- expression 10 operands: lhs = Expression(11, Sub), rhs = Counter(20) -- expression 11 operands: lhs = Expression(12, Sub), rhs = Counter(10) -- expression 12 operands: lhs = Counter(13), rhs = Counter(15) -- expression 13 operands: lhs = Counter(17), rhs = Counter(18) -- expression 14 operands: lhs = Counter(15), rhs = Expression(15, Add) -- expression 15 operands: lhs = Counter(17), rhs = Counter(18) -- expression 16 operands: lhs = Counter(21), rhs = Counter(22) -- expression 17 operands: lhs = Expression(21, Sub), rhs = Counter(9) -- expression 18 operands: lhs = Counter(21), rhs = Counter(22) -- expression 19 operands: lhs = Expression(20, Sub), rhs = Counter(30) -- expression 20 operands: lhs = Expression(21, Sub), rhs = Counter(9) -- expression 21 operands: lhs = Counter(21), rhs = Counter(22) -- expression 22 operands: lhs = Counter(23), rhs = Counter(24) -- expression 23 operands: lhs = Counter(22), rhs = Expression(24, Add) -- expression 24 operands: lhs = Counter(23), rhs = Counter(24) -- expression 25 operands: lhs = Counter(27), rhs = Expression(49, Add) -- expression 26 operands: lhs = Counter(28), rhs = Counter(29) -- expression 27 operands: lhs = Counter(25), rhs = Counter(27) -- expression 28 operands: lhs = Expression(32, Sub), rhs = Counter(8) -- expression 29 operands: lhs = Counter(25), rhs = Counter(27) -- expression 30 operands: lhs = Expression(31, Sub), rhs = Counter(31) -- expression 31 operands: lhs = Expression(32, Sub), rhs = Counter(8) -- expression 32 operands: lhs = Counter(25), rhs = Counter(27) -- expression 33 operands: lhs = Counter(28), rhs = Counter(29) -- expression 34 operands: lhs = Counter(4), rhs = Expression(53, Add) -- expression 35 operands: lhs = Counter(5), rhs = Counter(6) -- expression 36 operands: lhs = Counter(27), rhs = Expression(49, Add) -- expression 37 operands: lhs = Counter(28), rhs = Counter(29) -- expression 38 operands: lhs = Expression(48, Add), rhs = Counter(4) -- expression 39 operands: lhs = Counter(27), rhs = Expression(49, Add) -- expression 40 operands: lhs = Counter(28), rhs = Counter(29) -- expression 41 operands: lhs = Expression(47, Sub), rhs = Counter(7) -- expression 42 operands: lhs = Expression(48, Add), rhs = Counter(4) -- expression 43 operands: lhs = Counter(27), rhs = Expression(49, Add) -- expression 44 operands: lhs = Counter(28), rhs = Counter(29) -- expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(34) -- expression 46 operands: lhs = Expression(47, Sub), rhs = Counter(7) -- expression 47 operands: lhs = Expression(48, Add), rhs = Counter(4) -- expression 48 operands: lhs = Counter(27), rhs = Expression(49, Add) -- expression 49 operands: lhs = Counter(28), rhs = Counter(29) -- expression 50 operands: lhs = Counter(5), rhs = Counter(6) -- expression 51 operands: lhs = Expression(52, Add), rhs = Expression(54, Add) -- expression 52 operands: lhs = Counter(4), rhs = Expression(53, Add) -- expression 53 operands: lhs = Counter(5), rhs = Counter(6) -- expression 54 operands: lhs = Expression(55, Add), rhs = Expression(58, Sub) -- expression 55 operands: lhs = Expression(56, Add), rhs = Expression(57, Add) -- expression 56 operands: lhs = Counter(7), rhs = Counter(8) -- expression 57 operands: lhs = Counter(9), rhs = Counter(10) -- expression 58 operands: lhs = Expression(59, Sub), rhs = Counter(3) -- expression 59 operands: lhs = Counter(1), rhs = Counter(2) +Number of expressions: 141 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(2), rhs = Expression(37, Add) +- expression 2 operands: lhs = Counter(11), rhs = Counter(12) +- expression 3 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 4 operands: lhs = Expression(140, Add), rhs = Counter(2) +- expression 5 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 6 operands: lhs = Counter(3), rhs = Counter(14) +- expression 7 operands: lhs = Counter(11), rhs = Counter(12) +- expression 8 operands: lhs = Expression(139, Sub), rhs = Counter(3) +- expression 9 operands: lhs = Expression(140, Add), rhs = Counter(2) +- expression 10 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 11 operands: lhs = Counter(2), rhs = Expression(37, Add) +- expression 12 operands: lhs = Counter(11), rhs = Counter(12) +- expression 13 operands: lhs = Expression(36, Add), rhs = Counter(13) +- expression 14 operands: lhs = Counter(2), rhs = Expression(37, Add) +- expression 15 operands: lhs = Counter(11), rhs = Counter(12) +- expression 16 operands: lhs = Counter(13), rhs = Expression(35, Sub) +- expression 17 operands: lhs = Expression(36, Add), rhs = Counter(13) +- expression 18 operands: lhs = Counter(2), rhs = Expression(37, Add) +- expression 19 operands: lhs = Counter(11), rhs = Counter(12) +- expression 20 operands: lhs = Expression(34, Add), rhs = Counter(15) +- expression 21 operands: lhs = Counter(13), rhs = Expression(35, Sub) +- expression 22 operands: lhs = Expression(36, Add), rhs = Counter(13) +- expression 23 operands: lhs = Counter(2), rhs = Expression(37, Add) +- expression 24 operands: lhs = Counter(11), rhs = Counter(12) +- expression 25 operands: lhs = Expression(33, Sub), rhs = Counter(10) +- expression 26 operands: lhs = Expression(34, Add), rhs = Counter(15) +- expression 27 operands: lhs = Counter(13), rhs = Expression(35, Sub) +- expression 28 operands: lhs = Expression(36, Add), rhs = Counter(13) +- expression 29 operands: lhs = Counter(2), rhs = Expression(37, Add) +- expression 30 operands: lhs = Counter(11), rhs = Counter(12) +- expression 31 operands: lhs = Expression(32, Sub), rhs = Counter(20) +- expression 32 operands: lhs = Expression(33, Sub), rhs = Counter(10) +- expression 33 operands: lhs = Expression(34, Add), rhs = Counter(15) +- expression 34 operands: lhs = Counter(13), rhs = Expression(35, Sub) +- expression 35 operands: lhs = Expression(36, Add), rhs = Counter(13) +- expression 36 operands: lhs = Counter(2), rhs = Expression(37, Add) +- expression 37 operands: lhs = Counter(11), rhs = Counter(12) +- expression 38 operands: lhs = Counter(17), rhs = Counter(18) +- expression 39 operands: lhs = Counter(15), rhs = Expression(112, Add) +- expression 40 operands: lhs = Counter(17), rhs = Counter(18) +- expression 41 operands: lhs = Counter(19), rhs = Counter(21) +- expression 42 operands: lhs = Counter(21), rhs = Expression(55, Sub) +- expression 43 operands: lhs = Counter(19), rhs = Counter(21) +- expression 44 operands: lhs = Expression(54, Add), rhs = Counter(22) +- expression 45 operands: lhs = Counter(21), rhs = Expression(55, Sub) +- expression 46 operands: lhs = Counter(19), rhs = Counter(21) +- expression 47 operands: lhs = Expression(53, Sub), rhs = Counter(9) +- expression 48 operands: lhs = Expression(54, Add), rhs = Counter(22) +- expression 49 operands: lhs = Counter(21), rhs = Expression(55, Sub) +- expression 50 operands: lhs = Counter(19), rhs = Counter(21) +- expression 51 operands: lhs = Expression(52, Sub), rhs = Counter(30) +- expression 52 operands: lhs = Expression(53, Sub), rhs = Counter(9) +- expression 53 operands: lhs = Expression(54, Add), rhs = Counter(22) +- expression 54 operands: lhs = Counter(21), rhs = Expression(55, Sub) +- expression 55 operands: lhs = Counter(19), rhs = Counter(21) +- expression 56 operands: lhs = Counter(23), rhs = Counter(24) +- expression 57 operands: lhs = Expression(111, Add), rhs = Counter(19) +- expression 58 operands: lhs = Counter(15), rhs = Expression(112, Add) +- expression 59 operands: lhs = Counter(17), rhs = Counter(18) +- expression 60 operands: lhs = Expression(108, Add), rhs = Expression(110, Sub) +- expression 61 operands: lhs = Counter(22), rhs = Expression(109, Add) +- expression 62 operands: lhs = Counter(23), rhs = Counter(24) +- expression 63 operands: lhs = Expression(111, Add), rhs = Counter(19) +- expression 64 operands: lhs = Counter(15), rhs = Expression(112, Add) +- expression 65 operands: lhs = Counter(17), rhs = Counter(18) +- expression 66 operands: lhs = Expression(107, Add), rhs = Counter(25) +- expression 67 operands: lhs = Expression(108, Add), rhs = Expression(110, Sub) +- expression 68 operands: lhs = Counter(22), rhs = Expression(109, Add) +- expression 69 operands: lhs = Counter(23), rhs = Counter(24) +- expression 70 operands: lhs = Expression(111, Add), rhs = Counter(19) +- expression 71 operands: lhs = Counter(15), rhs = Expression(112, Add) +- expression 72 operands: lhs = Counter(17), rhs = Counter(18) +- expression 73 operands: lhs = Counter(27), rhs = Expression(129, Add) +- expression 74 operands: lhs = Counter(28), rhs = Counter(29) +- expression 75 operands: lhs = Counter(25), rhs = Expression(106, Sub) +- expression 76 operands: lhs = Expression(107, Add), rhs = Counter(25) +- expression 77 operands: lhs = Expression(108, Add), rhs = Expression(110, Sub) +- expression 78 operands: lhs = Counter(22), rhs = Expression(109, Add) +- expression 79 operands: lhs = Counter(23), rhs = Counter(24) +- expression 80 operands: lhs = Expression(111, Add), rhs = Counter(19) +- expression 81 operands: lhs = Counter(15), rhs = Expression(112, Add) +- expression 82 operands: lhs = Counter(17), rhs = Counter(18) +- expression 83 operands: lhs = Expression(105, Add), rhs = Counter(27) +- expression 84 operands: lhs = Counter(25), rhs = Expression(106, Sub) +- expression 85 operands: lhs = Expression(107, Add), rhs = Counter(25) +- expression 86 operands: lhs = Expression(108, Add), rhs = Expression(110, Sub) +- expression 87 operands: lhs = Counter(22), rhs = Expression(109, Add) +- expression 88 operands: lhs = Counter(23), rhs = Counter(24) +- expression 89 operands: lhs = Expression(111, Add), rhs = Counter(19) +- expression 90 operands: lhs = Counter(15), rhs = Expression(112, Add) +- expression 91 operands: lhs = Counter(17), rhs = Counter(18) +- expression 92 operands: lhs = Expression(104, Sub), rhs = Counter(8) +- expression 93 operands: lhs = Expression(105, Add), rhs = Counter(27) +- expression 94 operands: lhs = Counter(25), rhs = Expression(106, Sub) +- expression 95 operands: lhs = Expression(107, Add), rhs = Counter(25) +- expression 96 operands: lhs = Expression(108, Add), rhs = Expression(110, Sub) +- expression 97 operands: lhs = Counter(22), rhs = Expression(109, Add) +- expression 98 operands: lhs = Counter(23), rhs = Counter(24) +- expression 99 operands: lhs = Expression(111, Add), rhs = Counter(19) +- expression 100 operands: lhs = Counter(15), rhs = Expression(112, Add) +- expression 101 operands: lhs = Counter(17), rhs = Counter(18) +- expression 102 operands: lhs = Expression(103, Sub), rhs = Counter(31) +- expression 103 operands: lhs = Expression(104, Sub), rhs = Counter(8) +- expression 104 operands: lhs = Expression(105, Add), rhs = Counter(27) +- expression 105 operands: lhs = Counter(25), rhs = Expression(106, Sub) +- expression 106 operands: lhs = Expression(107, Add), rhs = Counter(25) +- expression 107 operands: lhs = Expression(108, Add), rhs = Expression(110, Sub) +- expression 108 operands: lhs = Counter(22), rhs = Expression(109, Add) +- expression 109 operands: lhs = Counter(23), rhs = Counter(24) +- expression 110 operands: lhs = Expression(111, Add), rhs = Counter(19) +- expression 111 operands: lhs = Counter(15), rhs = Expression(112, Add) +- expression 112 operands: lhs = Counter(17), rhs = Counter(18) +- expression 113 operands: lhs = Counter(28), rhs = Counter(29) +- expression 114 operands: lhs = Counter(4), rhs = Expression(133, Add) +- expression 115 operands: lhs = Counter(5), rhs = Counter(6) +- expression 116 operands: lhs = Counter(27), rhs = Expression(129, Add) +- expression 117 operands: lhs = Counter(28), rhs = Counter(29) +- expression 118 operands: lhs = Expression(128, Add), rhs = Counter(4) +- expression 119 operands: lhs = Counter(27), rhs = Expression(129, Add) +- expression 120 operands: lhs = Counter(28), rhs = Counter(29) +- expression 121 operands: lhs = Expression(127, Sub), rhs = Counter(7) +- expression 122 operands: lhs = Expression(128, Add), rhs = Counter(4) +- expression 123 operands: lhs = Counter(27), rhs = Expression(129, Add) +- expression 124 operands: lhs = Counter(28), rhs = Counter(29) +- expression 125 operands: lhs = Expression(126, Sub), rhs = Counter(34) +- expression 126 operands: lhs = Expression(127, Sub), rhs = Counter(7) +- expression 127 operands: lhs = Expression(128, Add), rhs = Counter(4) +- expression 128 operands: lhs = Counter(27), rhs = Expression(129, Add) +- expression 129 operands: lhs = Counter(28), rhs = Counter(29) +- expression 130 operands: lhs = Counter(5), rhs = Counter(6) +- expression 131 operands: lhs = Expression(132, Add), rhs = Expression(134, Add) +- expression 132 operands: lhs = Counter(4), rhs = Expression(133, Add) +- expression 133 operands: lhs = Counter(5), rhs = Counter(6) +- expression 134 operands: lhs = Expression(135, Add), rhs = Expression(138, Sub) +- expression 135 operands: lhs = Expression(136, Add), rhs = Expression(137, Add) +- expression 136 operands: lhs = Counter(7), rhs = Counter(8) +- expression 137 operands: lhs = Counter(9), rhs = Counter(10) +- expression 138 operands: lhs = Expression(139, Sub), rhs = Counter(3) +- expression 139 operands: lhs = Expression(140, Add), rhs = Counter(2) +- expression 140 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 68 - Code(Counter(0)) at (prev + 3, 1) to (start + 2, 12) - Code(Counter(1)) at (prev + 2, 13) to (start + 2, 6) -- Code(Zero) at (prev + 2, 6) to (start + 0, 7) -- Code(Expression(0, Add)) at (prev + 3, 9) to (start + 0, 10) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(36, Add)) at (prev + 3, 9) to (start + 0, 10) = (c2 + (c11 + c12)) -- Code(Counter(1)) at (prev + 0, 16) to (start + 0, 29) +- Code(Expression(140, Add)) at (prev + 0, 16) to (start + 0, 29) + = (c1 + (c0 - c1)) - Code(Counter(2)) at (prev + 1, 9) to (start + 1, 10) -- Code(Expression(59, Sub)) at (prev + 2, 15) to (start + 0, 28) - = (c1 - c2) +- Code(Expression(139, Sub)) at (prev + 2, 15) to (start + 0, 28) + = ((c1 + (c0 - c1)) - c2) - Code(Counter(3)) at (prev + 1, 12) to (start + 0, 25) -- Code(Expression(3, Sub)) at (prev + 0, 29) to (start + 0, 42) +- Code(Expression(6, Sub)) at (prev + 0, 29) to (start + 0, 42) = (c3 - c14) - Code(Counter(16)) at (prev + 0, 46) to (start + 0, 60) - Code(Counter(11)) at (prev + 0, 61) to (start + 2, 10) - Code(Counter(12)) at (prev + 2, 10) to (start + 0, 11) -- Code(Expression(4, Add)) at (prev + 1, 9) to (start + 1, 18) +- Code(Expression(37, Add)) at (prev + 1, 9) to (start + 1, 18) = (c11 + c12) -- Code(Expression(58, Sub)) at (prev + 3, 9) to (start + 0, 15) - = ((c1 - c2) - c3) -- Code(Expression(0, Add)) at (prev + 3, 9) to (start + 1, 12) +- Code(Expression(138, Sub)) at (prev + 3, 9) to (start + 0, 15) + = (((c1 + (c0 - c1)) - c2) - c3) +- Code(Expression(36, Add)) at (prev + 3, 9) to (start + 1, 12) = (c2 + (c11 + c12)) - Code(Counter(13)) at (prev + 1, 13) to (start + 2, 6) -- Code(Zero) at (prev + 2, 6) to (start + 0, 7) -- Code(Counter(13)) at (prev + 2, 8) to (start + 0, 21) +- Code(Expression(35, Sub)) at (prev + 2, 6) to (start + 0, 7) + = ((c2 + (c11 + c12)) - c13) +- Code(Expression(34, Add)) at (prev + 2, 8) to (start + 0, 21) + = (c13 + ((c2 + (c11 + c12)) - c13)) - Code(Counter(15)) at (prev + 0, 22) to (start + 2, 6) -- Code(Expression(12, Sub)) at (prev + 2, 15) to (start + 0, 28) - = (c13 - c15) -- Code(Expression(11, Sub)) at (prev + 1, 12) to (start + 0, 25) - = ((c13 - c15) - c10) -- Code(Expression(10, Sub)) at (prev + 0, 29) to (start + 0, 42) - = (((c13 - c15) - c10) - c20) +- Code(Expression(33, Sub)) at (prev + 2, 15) to (start + 0, 28) + = ((c13 + ((c2 + (c11 + c12)) - c13)) - c15) +- Code(Expression(32, Sub)) at (prev + 1, 12) to (start + 0, 25) + = (((c13 + ((c2 + (c11 + c12)) - c13)) - c15) - c10) +- Code(Expression(31, Sub)) at (prev + 0, 29) to (start + 0, 42) + = ((((c13 + ((c2 + (c11 + c12)) - c13)) - c15) - c10) - c20) - Code(Counter(26)) at (prev + 0, 46) to (start + 0, 60) - Code(Counter(17)) at (prev + 0, 61) to (start + 2, 10) - Code(Counter(18)) at (prev + 2, 10) to (start + 0, 11) -- Code(Expression(15, Add)) at (prev + 1, 9) to (start + 0, 23) +- Code(Expression(112, Add)) at (prev + 1, 9) to (start + 0, 23) = (c17 + c18) - Code(Counter(10)) at (prev + 2, 9) to (start + 0, 15) -- Code(Expression(14, Add)) at (prev + 3, 8) to (start + 0, 12) +- Code(Expression(111, Add)) at (prev + 3, 8) to (start + 0, 12) = (c15 + (c17 + c18)) - Code(Counter(19)) at (prev + 1, 13) to (start + 1, 16) - Code(Counter(21)) at (prev + 1, 17) to (start + 2, 10) -- Code(Zero) at (prev + 2, 10) to (start + 0, 11) -- Code(Counter(21)) at (prev + 2, 12) to (start + 0, 25) +- Code(Expression(55, Sub)) at (prev + 2, 10) to (start + 0, 11) + = (c19 - c21) +- Code(Expression(54, Add)) at (prev + 2, 12) to (start + 0, 25) + = (c21 + (c19 - c21)) - Code(Counter(22)) at (prev + 0, 26) to (start + 2, 10) -- Code(Expression(21, Sub)) at (prev + 3, 17) to (start + 0, 30) - = (c21 - c22) -- Code(Expression(20, Sub)) at (prev + 1, 16) to (start + 0, 29) - = ((c21 - c22) - c9) -- Code(Expression(19, Sub)) at (prev + 0, 33) to (start + 0, 46) - = (((c21 - c22) - c9) - c30) +- Code(Expression(53, Sub)) at (prev + 3, 17) to (start + 0, 30) + = ((c21 + (c19 - c21)) - c22) +- Code(Expression(52, Sub)) at (prev + 1, 16) to (start + 0, 29) + = (((c21 + (c19 - c21)) - c22) - c9) +- Code(Expression(51, Sub)) at (prev + 0, 33) to (start + 0, 46) + = ((((c21 + (c19 - c21)) - c22) - c9) - c30) - Code(Counter(32)) at (prev + 0, 50) to (start + 0, 64) - Code(Counter(23)) at (prev + 0, 65) to (start + 2, 14) - Code(Counter(24)) at (prev + 2, 14) to (start + 0, 15) -- Code(Expression(24, Add)) at (prev + 1, 13) to (start + 0, 27) +- Code(Expression(109, Add)) at (prev + 1, 13) to (start + 0, 27) = (c23 + c24) - Code(Counter(9)) at (prev + 2, 13) to (start + 0, 19) -- Code(Zero) at (prev + 2, 6) to (start + 0, 7) -- Code(Expression(23, Add)) at (prev + 3, 9) to (start + 1, 12) - = (c22 + (c23 + c24)) +- Code(Expression(110, Sub)) at (prev + 2, 6) to (start + 0, 7) + = ((c15 + (c17 + c18)) - c19) +- Code(Expression(107, Add)) at (prev + 3, 9) to (start + 1, 12) + = ((c22 + (c23 + c24)) + ((c15 + (c17 + c18)) - c19)) - Code(Counter(25)) at (prev + 1, 13) to (start + 2, 6) -- Code(Zero) at (prev + 2, 6) to (start + 0, 7) -- Code(Expression(48, Add)) at (prev + 2, 9) to (start + 0, 10) +- Code(Expression(106, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (((c22 + (c23 + c24)) + ((c15 + (c17 + c18)) - c19)) - c25) +- Code(Expression(128, Add)) at (prev + 2, 9) to (start + 0, 10) = (c27 + (c28 + c29)) -- Code(Counter(25)) at (prev + 0, 16) to (start + 0, 29) +- Code(Expression(105, Add)) at (prev + 0, 16) to (start + 0, 29) + = (c25 + (((c22 + (c23 + c24)) + ((c15 + (c17 + c18)) - c19)) - c25)) - Code(Counter(27)) at (prev + 0, 30) to (start + 2, 6) -- Code(Expression(32, Sub)) at (prev + 2, 15) to (start + 0, 28) - = (c25 - c27) -- Code(Expression(31, Sub)) at (prev + 1, 12) to (start + 0, 25) - = ((c25 - c27) - c8) -- Code(Expression(30, Sub)) at (prev + 0, 29) to (start + 0, 42) - = (((c25 - c27) - c8) - c31) +- Code(Expression(104, Sub)) at (prev + 2, 15) to (start + 0, 28) + = ((c25 + (((c22 + (c23 + c24)) + ((c15 + (c17 + c18)) - c19)) - c25)) - c27) +- Code(Expression(103, Sub)) at (prev + 1, 12) to (start + 0, 25) + = (((c25 + (((c22 + (c23 + c24)) + ((c15 + (c17 + c18)) - c19)) - c25)) - c27) - c8) +- Code(Expression(102, Sub)) at (prev + 0, 29) to (start + 0, 42) + = ((((c25 + (((c22 + (c23 + c24)) + ((c15 + (c17 + c18)) - c19)) - c25)) - c27) - c8) - c31) - Code(Counter(33)) at (prev + 0, 46) to (start + 0, 60) - Code(Counter(28)) at (prev + 0, 61) to (start + 2, 10) - Code(Counter(29)) at (prev + 2, 10) to (start + 0, 11) -- Code(Expression(49, Add)) at (prev + 1, 9) to (start + 0, 23) +- Code(Expression(129, Add)) at (prev + 1, 9) to (start + 0, 23) = (c28 + c29) - Code(Counter(8)) at (prev + 2, 13) to (start + 2, 15) -- Code(Expression(52, Add)) at (prev + 5, 9) to (start + 0, 10) +- Code(Expression(132, Add)) at (prev + 5, 9) to (start + 0, 10) = (c4 + (c5 + c6)) -- Code(Expression(48, Add)) at (prev + 0, 16) to (start + 0, 29) +- Code(Expression(128, Add)) at (prev + 0, 16) to (start + 0, 29) = (c27 + (c28 + c29)) - Code(Counter(4)) at (prev + 0, 30) to (start + 2, 6) -- Code(Expression(47, Sub)) at (prev + 2, 15) to (start + 0, 28) +- Code(Expression(127, Sub)) at (prev + 2, 15) to (start + 0, 28) = ((c27 + (c28 + c29)) - c4) -- Code(Expression(46, Sub)) at (prev + 1, 12) to (start + 0, 25) +- Code(Expression(126, Sub)) at (prev + 1, 12) to (start + 0, 25) = (((c27 + (c28 + c29)) - c4) - c7) -- Code(Expression(45, Sub)) at (prev + 0, 29) to (start + 0, 42) +- Code(Expression(125, Sub)) at (prev + 0, 29) to (start + 0, 42) = ((((c27 + (c28 + c29)) - c4) - c7) - c34) - Code(Counter(35)) at (prev + 0, 46) to (start + 0, 60) - Code(Counter(5)) at (prev + 0, 61) to (start + 2, 10) - Code(Counter(6)) at (prev + 2, 10) to (start + 0, 11) -- Code(Expression(53, Add)) at (prev + 1, 9) to (start + 0, 23) +- Code(Expression(133, Add)) at (prev + 1, 9) to (start + 0, 23) = (c5 + c6) - Code(Counter(7)) at (prev + 2, 9) to (start + 0, 15) -- Code(Expression(51, Add)) at (prev + 2, 1) to (start + 0, 2) - = ((c4 + (c5 + c6)) + (((c7 + c8) + (c9 + c10)) + ((c1 - c2) - c3))) +- Code(Expression(131, Add)) at (prev + 2, 1) to (start + 0, 2) + = ((c4 + (c5 + c6)) + (((c7 + c8) + (c9 + c10)) + (((c1 + (c0 - c1)) - c2) - c3))) diff --git a/tests/coverage-map/status-quo/drop_trait.cov-map b/tests/coverage-map/status-quo/drop_trait.cov-map index cf3df9fce1d23..353f7e94492a0 100644 --- a/tests/coverage-map/status-quo/drop_trait.cov-map +++ b/tests/coverage-map/status-quo/drop_trait.cov-map @@ -7,13 +7,17 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 9, 5) to (start + 2, 6) Function name: drop_trait::main -Raw bytes (24): 0x[01, 01, 00, 04, 01, 0e, 01, 05, 0c, 05, 06, 09, 01, 16, 00, 02, 06, 04, 0b, 05, 05, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 0e, 01, 05, 0c, 05, 06, 09, 01, 16, 02, 02, 06, 04, 0b, 07, 05, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 0 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 14, 1) to (start + 5, 12) - Code(Counter(1)) at (prev + 6, 9) to (start + 1, 22) -- Code(Zero) at (prev + 2, 6) to (start + 4, 11) -- Code(Counter(1)) at (prev + 5, 1) to (start + 0, 2) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 4, 11) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 5, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) diff --git a/tests/coverage-map/status-quo/generics.cov-map b/tests/coverage-map/status-quo/generics.cov-map index b7e3c772dd237..d6599940200a2 100644 --- a/tests/coverage-map/status-quo/generics.cov-map +++ b/tests/coverage-map/status-quo/generics.cov-map @@ -31,13 +31,17 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 10, 5) to (start + 2, 6) Function name: generics::main -Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 01, 08, 0c, 05, 09, 09, 01, 16, 00, 02, 06, 08, 0b, 05, 09, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 16, 01, 08, 0c, 05, 09, 09, 01, 16, 02, 02, 06, 08, 0b, 07, 09, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 0 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 22, 1) to (start + 8, 12) - Code(Counter(1)) at (prev + 9, 9) to (start + 1, 22) -- Code(Zero) at (prev + 2, 6) to (start + 8, 11) -- Code(Counter(1)) at (prev + 9, 1) to (start + 0, 2) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 8, 11) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 9, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) diff --git a/tests/coverage-map/status-quo/loops_branches.cov-map b/tests/coverage-map/status-quo/loops_branches.cov-map index 199f9aa9830f8..381c9e6b68591 100644 --- a/tests/coverage-map/status-quo/loops_branches.cov-map +++ b/tests/coverage-map/status-quo/loops_branches.cov-map @@ -1,161 +1,108 @@ Function name: ::fmt -Raw bytes (210): 0x[01, 01, 25, 05, 09, 8f, 01, 19, 0d, 93, 01, 11, 15, 0d, 93, 01, 11, 15, 8f, 01, 19, 0d, 93, 01, 11, 15, 8a, 01, 15, 8f, 01, 19, 0d, 93, 01, 11, 15, 86, 01, 1d, 8a, 01, 15, 8f, 01, 19, 0d, 93, 01, 11, 15, 86, 01, 1d, 8a, 01, 15, 8f, 01, 19, 0d, 93, 01, 11, 15, 82, 01, 11, 86, 01, 1d, 8a, 01, 15, 8f, 01, 19, 0d, 93, 01, 11, 15, 25, 7b, 7e, 19, 82, 01, 11, 86, 01, 1d, 8a, 01, 15, 8f, 01, 19, 0d, 93, 01, 11, 15, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 01, 12, 02, 02, 0e, 00, 0f, 02, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 8a, 01, 03, 0d, 00, 0e, 8f, 01, 00, 12, 00, 17, 8a, 01, 01, 10, 00, 14, 86, 01, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 82, 01, 01, 12, 00, 13, 82, 01, 01, 11, 00, 22, 7e, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, 77, 01, 05, 00, 06] +Raw bytes (160): 0x[01, 01, 1c, 01, 05, 6b, 19, 6f, 11, 0d, 02, 6f, 11, 0d, 02, 6b, 19, 6f, 11, 0d, 02, 6b, 19, 6f, 11, 0d, 02, 6b, 19, 6f, 11, 0d, 02, 6b, 19, 6f, 11, 0d, 02, 66, 11, 6b, 19, 6f, 11, 0d, 02, 25, 5f, 62, 19, 66, 11, 6b, 19, 6f, 11, 0d, 02, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 01, 12, 05, 02, 0e, 00, 0f, 05, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 02, 01, 10, 01, 0a, 66, 03, 0d, 00, 0e, 6b, 00, 12, 00, 17, 66, 01, 10, 00, 14, 66, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 66, 01, 12, 00, 13, 66, 01, 11, 00, 22, 62, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, 5b, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 -Number of expressions: 37 -- expression 0 operands: lhs = Counter(1), rhs = Counter(2) -- expression 1 operands: lhs = Expression(35, Add), rhs = Counter(6) -- expression 2 operands: lhs = Counter(3), rhs = Expression(36, Add) -- expression 3 operands: lhs = Counter(4), rhs = Counter(5) -- expression 4 operands: lhs = Counter(3), rhs = Expression(36, Add) -- expression 5 operands: lhs = Counter(4), rhs = Counter(5) -- expression 6 operands: lhs = Expression(35, Add), rhs = Counter(6) -- expression 7 operands: lhs = Counter(3), rhs = Expression(36, Add) -- expression 8 operands: lhs = Counter(4), rhs = Counter(5) -- expression 9 operands: lhs = Expression(34, Sub), rhs = Counter(5) -- expression 10 operands: lhs = Expression(35, Add), rhs = Counter(6) -- expression 11 operands: lhs = Counter(3), rhs = Expression(36, Add) -- expression 12 operands: lhs = Counter(4), rhs = Counter(5) -- expression 13 operands: lhs = Expression(33, Sub), rhs = Counter(7) -- expression 14 operands: lhs = Expression(34, Sub), rhs = Counter(5) -- expression 15 operands: lhs = Expression(35, Add), rhs = Counter(6) -- expression 16 operands: lhs = Counter(3), rhs = Expression(36, Add) -- expression 17 operands: lhs = Counter(4), rhs = Counter(5) -- expression 18 operands: lhs = Expression(33, Sub), rhs = Counter(7) -- expression 19 operands: lhs = Expression(34, Sub), rhs = Counter(5) -- expression 20 operands: lhs = Expression(35, Add), rhs = Counter(6) -- expression 21 operands: lhs = Counter(3), rhs = Expression(36, Add) -- expression 22 operands: lhs = Counter(4), rhs = Counter(5) -- expression 23 operands: lhs = Expression(32, Sub), rhs = Counter(4) -- expression 24 operands: lhs = Expression(33, Sub), rhs = Counter(7) -- expression 25 operands: lhs = Expression(34, Sub), rhs = Counter(5) -- expression 26 operands: lhs = Expression(35, Add), rhs = Counter(6) -- expression 27 operands: lhs = Counter(3), rhs = Expression(36, Add) -- expression 28 operands: lhs = Counter(4), rhs = Counter(5) -- expression 29 operands: lhs = Counter(9), rhs = Expression(30, Add) -- expression 30 operands: lhs = Expression(31, Sub), rhs = Counter(6) -- expression 31 operands: lhs = Expression(32, Sub), rhs = Counter(4) -- expression 32 operands: lhs = Expression(33, Sub), rhs = Counter(7) -- expression 33 operands: lhs = Expression(34, Sub), rhs = Counter(5) -- expression 34 operands: lhs = Expression(35, Add), rhs = Counter(6) -- expression 35 operands: lhs = Counter(3), rhs = Expression(36, Add) -- expression 36 operands: lhs = Counter(4), rhs = Counter(5) +Number of expressions: 28 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Expression(26, Add), rhs = Counter(6) +- expression 2 operands: lhs = Expression(27, Add), rhs = Counter(4) +- expression 3 operands: lhs = Counter(3), rhs = Expression(0, Sub) +- expression 4 operands: lhs = Expression(27, Add), rhs = Counter(4) +- expression 5 operands: lhs = Counter(3), rhs = Expression(0, Sub) +- expression 6 operands: lhs = Expression(26, Add), rhs = Counter(6) +- expression 7 operands: lhs = Expression(27, Add), rhs = Counter(4) +- expression 8 operands: lhs = Counter(3), rhs = Expression(0, Sub) +- expression 9 operands: lhs = Expression(26, Add), rhs = Counter(6) +- expression 10 operands: lhs = Expression(27, Add), rhs = Counter(4) +- expression 11 operands: lhs = Counter(3), rhs = Expression(0, Sub) +- expression 12 operands: lhs = Expression(26, Add), rhs = Counter(6) +- expression 13 operands: lhs = Expression(27, Add), rhs = Counter(4) +- expression 14 operands: lhs = Counter(3), rhs = Expression(0, Sub) +- expression 15 operands: lhs = Expression(26, Add), rhs = Counter(6) +- expression 16 operands: lhs = Expression(27, Add), rhs = Counter(4) +- expression 17 operands: lhs = Counter(3), rhs = Expression(0, Sub) +- expression 18 operands: lhs = Expression(25, Sub), rhs = Counter(4) +- expression 19 operands: lhs = Expression(26, Add), rhs = Counter(6) +- expression 20 operands: lhs = Expression(27, Add), rhs = Counter(4) +- expression 21 operands: lhs = Counter(3), rhs = Expression(0, Sub) +- expression 22 operands: lhs = Counter(9), rhs = Expression(23, Add) +- expression 23 operands: lhs = Expression(24, Sub), rhs = Counter(6) +- expression 24 operands: lhs = Expression(25, Sub), rhs = Counter(4) +- expression 25 operands: lhs = Expression(26, Add), rhs = Counter(6) +- expression 26 operands: lhs = Expression(27, Add), rhs = Counter(4) +- expression 27 operands: lhs = Counter(3), rhs = Expression(0, Sub) Number of file 0 mappings: 20 - Code(Counter(0)) at (prev + 9, 5) to (start + 1, 16) - Code(Counter(1)) at (prev + 2, 16) to (start + 0, 21) - Code(Zero) at (prev + 1, 23) to (start + 0, 27) - Code(Zero) at (prev + 0, 28) to (start + 1, 18) -- Code(Expression(0, Sub)) at (prev + 2, 14) to (start + 0, 15) - = (c1 - c2) -- Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 30) - = (c1 - c2) +- Code(Counter(1)) at (prev + 2, 14) to (start + 0, 15) +- Code(Counter(1)) at (prev + 1, 13) to (start + 0, 30) - Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31) -- Code(Zero) at (prev + 1, 16) to (start + 1, 10) -- Code(Expression(34, Sub)) at (prev + 3, 13) to (start + 0, 14) - = ((c3 + (c4 + c5)) - c6) -- Code(Expression(35, Add)) at (prev + 0, 18) to (start + 0, 23) - = (c3 + (c4 + c5)) -- Code(Expression(34, Sub)) at (prev + 1, 16) to (start + 0, 20) - = ((c3 + (c4 + c5)) - c6) -- Code(Expression(33, Sub)) at (prev + 1, 20) to (start + 0, 25) - = (((c3 + (c4 + c5)) - c6) - c5) +- Code(Expression(0, Sub)) at (prev + 1, 16) to (start + 1, 10) + = (c0 - c1) +- Code(Expression(25, Sub)) at (prev + 3, 13) to (start + 0, 14) + = (((c3 + (c0 - c1)) + c4) - c6) +- Code(Expression(26, Add)) at (prev + 0, 18) to (start + 0, 23) + = ((c3 + (c0 - c1)) + c4) +- Code(Expression(25, Sub)) at (prev + 1, 16) to (start + 0, 20) + = (((c3 + (c0 - c1)) + c4) - c6) +- Code(Expression(25, Sub)) at (prev + 1, 20) to (start + 0, 25) + = (((c3 + (c0 - c1)) + c4) - c6) - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) -- Code(Expression(32, Sub)) at (prev + 1, 18) to (start + 0, 19) - = ((((c3 + (c4 + c5)) - c6) - c5) - c7) -- Code(Expression(32, Sub)) at (prev + 1, 17) to (start + 0, 34) - = ((((c3 + (c4 + c5)) - c6) - c5) - c7) -- Code(Expression(31, Sub)) at (prev + 0, 34) to (start + 0, 35) - = (((((c3 + (c4 + c5)) - c6) - c5) - c7) - c4) +- Code(Expression(25, Sub)) at (prev + 1, 18) to (start + 0, 19) + = (((c3 + (c0 - c1)) + c4) - c6) +- Code(Expression(25, Sub)) at (prev + 1, 17) to (start + 0, 34) + = (((c3 + (c0 - c1)) + c4) - c6) +- Code(Expression(24, Sub)) at (prev + 0, 34) to (start + 0, 35) + = ((((c3 + (c0 - c1)) + c4) - c6) - c4) - Code(Zero) at (prev + 1, 20) to (start + 1, 14) - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) -- Code(Expression(29, Add)) at (prev + 1, 5) to (start + 0, 6) - = (c9 + ((((((c3 + (c4 + c5)) - c6) - c5) - c7) - c4) + c6)) +- Code(Expression(22, Add)) at (prev + 1, 5) to (start + 0, 6) + = (c9 + (((((c3 + (c0 - c1)) + c4) - c6) - c4) + c6)) Function name: ::fmt -Raw bytes (242): 0x[01, 01, 2f, 01, 05, 02, 09, 02, 09, af, 01, 19, b3, 01, b7, 01, 05, 0d, 11, 15, b3, 01, b7, 01, 05, 0d, 11, 15, af, 01, 19, b3, 01, b7, 01, 05, 0d, 11, 15, aa, 01, 11, af, 01, 19, b3, 01, b7, 01, 05, 0d, 11, 15, a6, 01, 1d, aa, 01, 11, af, 01, 19, b3, 01, b7, 01, 05, 0d, 11, 15, a6, 01, 1d, aa, 01, 11, af, 01, 19, b3, 01, b7, 01, 05, 0d, 11, 15, a2, 01, 15, a6, 01, 1d, aa, 01, 11, af, 01, 19, b3, 01, b7, 01, 05, 0d, 11, 15, 9e, 01, bb, 01, a2, 01, 15, a6, 01, 1d, aa, 01, 11, af, 01, 19, b3, 01, b7, 01, 05, 0d, 11, 15, 19, 25, 14, 01, 23, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 0a, 01, 0e, 00, 0f, 0a, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, aa, 01, 02, 0d, 00, 0e, af, 01, 00, 12, 00, 17, aa, 01, 01, 10, 00, 15, 00, 00, 16, 01, 0e, a6, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, a2, 01, 01, 12, 00, 13, a2, 01, 01, 11, 00, 22, 9e, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, 9b, 01, 01, 05, 00, 06] +Raw bytes (118): 0x[01, 01, 07, 0b, 19, 0d, 15, 0d, 15, 02, 15, 16, 1b, 02, 15, 19, 25, 14, 01, 23, 05, 01, 11, 00, 01, 12, 01, 0a, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0e, 00, 0f, 01, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 02, 02, 0d, 00, 0e, 0b, 00, 12, 00, 17, 02, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 02, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 02, 01, 12, 00, 13, 02, 01, 11, 00, 22, 16, 00, 22, 00, 23, 19, 03, 09, 00, 0f, 13, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 -Number of expressions: 47 -- expression 0 operands: lhs = Counter(0), rhs = Counter(1) -- expression 1 operands: lhs = Expression(0, Sub), rhs = Counter(2) -- expression 2 operands: lhs = Expression(0, Sub), rhs = Counter(2) -- expression 3 operands: lhs = Expression(43, Add), rhs = Counter(6) -- expression 4 operands: lhs = Expression(44, Add), rhs = Expression(45, Add) -- expression 5 operands: lhs = Counter(1), rhs = Counter(3) -- expression 6 operands: lhs = Counter(4), rhs = Counter(5) -- expression 7 operands: lhs = Expression(44, Add), rhs = Expression(45, Add) -- expression 8 operands: lhs = Counter(1), rhs = Counter(3) -- expression 9 operands: lhs = Counter(4), rhs = Counter(5) -- expression 10 operands: lhs = Expression(43, Add), rhs = Counter(6) -- expression 11 operands: lhs = Expression(44, Add), rhs = Expression(45, Add) -- expression 12 operands: lhs = Counter(1), rhs = Counter(3) -- expression 13 operands: lhs = Counter(4), rhs = Counter(5) -- expression 14 operands: lhs = Expression(42, Sub), rhs = Counter(4) -- expression 15 operands: lhs = Expression(43, Add), rhs = Counter(6) -- expression 16 operands: lhs = Expression(44, Add), rhs = Expression(45, Add) -- expression 17 operands: lhs = Counter(1), rhs = Counter(3) -- expression 18 operands: lhs = Counter(4), rhs = Counter(5) -- expression 19 operands: lhs = Expression(41, Sub), rhs = Counter(7) -- expression 20 operands: lhs = Expression(42, Sub), rhs = Counter(4) -- expression 21 operands: lhs = Expression(43, Add), rhs = Counter(6) -- expression 22 operands: lhs = Expression(44, Add), rhs = Expression(45, Add) -- expression 23 operands: lhs = Counter(1), rhs = Counter(3) -- expression 24 operands: lhs = Counter(4), rhs = Counter(5) -- expression 25 operands: lhs = Expression(41, Sub), rhs = Counter(7) -- expression 26 operands: lhs = Expression(42, Sub), rhs = Counter(4) -- expression 27 operands: lhs = Expression(43, Add), rhs = Counter(6) -- expression 28 operands: lhs = Expression(44, Add), rhs = Expression(45, Add) -- expression 29 operands: lhs = Counter(1), rhs = Counter(3) -- expression 30 operands: lhs = Counter(4), rhs = Counter(5) -- expression 31 operands: lhs = Expression(40, Sub), rhs = Counter(5) -- expression 32 operands: lhs = Expression(41, Sub), rhs = Counter(7) -- expression 33 operands: lhs = Expression(42, Sub), rhs = Counter(4) -- expression 34 operands: lhs = Expression(43, Add), rhs = Counter(6) -- expression 35 operands: lhs = Expression(44, Add), rhs = Expression(45, Add) -- expression 36 operands: lhs = Counter(1), rhs = Counter(3) -- expression 37 operands: lhs = Counter(4), rhs = Counter(5) -- expression 38 operands: lhs = Expression(39, Sub), rhs = Expression(46, Add) -- expression 39 operands: lhs = Expression(40, Sub), rhs = Counter(5) -- expression 40 operands: lhs = Expression(41, Sub), rhs = Counter(7) -- expression 41 operands: lhs = Expression(42, Sub), rhs = Counter(4) -- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(6) -- expression 43 operands: lhs = Expression(44, Add), rhs = Expression(45, Add) -- expression 44 operands: lhs = Counter(1), rhs = Counter(3) -- expression 45 operands: lhs = Counter(4), rhs = Counter(5) -- expression 46 operands: lhs = Counter(6), rhs = Counter(9) +Number of expressions: 7 +- expression 0 operands: lhs = Expression(2, Add), rhs = Counter(6) +- expression 1 operands: lhs = Counter(3), rhs = Counter(5) +- expression 2 operands: lhs = Counter(3), rhs = Counter(5) +- expression 3 operands: lhs = Expression(0, Sub), rhs = Counter(5) +- expression 4 operands: lhs = Expression(5, Sub), rhs = Expression(6, Add) +- expression 5 operands: lhs = Expression(0, Sub), rhs = Counter(5) +- expression 6 operands: lhs = Counter(6), rhs = Counter(9) Number of file 0 mappings: 20 - Code(Counter(0)) at (prev + 35, 5) to (start + 1, 17) - Code(Zero) at (prev + 1, 18) to (start + 1, 10) -- Code(Expression(0, Sub)) at (prev + 2, 16) to (start + 0, 21) - = (c0 - c1) +- Code(Counter(0)) at (prev + 2, 16) to (start + 0, 21) - Code(Zero) at (prev + 1, 23) to (start + 0, 27) - Code(Zero) at (prev + 0, 28) to (start + 0, 30) -- Code(Expression(2, Sub)) at (prev + 1, 14) to (start + 0, 15) - = ((c0 - c1) - c2) -- Code(Expression(2, Sub)) at (prev + 1, 13) to (start + 0, 30) - = ((c0 - c1) - c2) +- Code(Counter(0)) at (prev + 1, 14) to (start + 0, 15) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 30) - Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31) -- Code(Expression(42, Sub)) at (prev + 2, 13) to (start + 0, 14) - = (((c1 + c3) + (c4 + c5)) - c6) -- Code(Expression(43, Add)) at (prev + 0, 18) to (start + 0, 23) - = ((c1 + c3) + (c4 + c5)) -- Code(Expression(42, Sub)) at (prev + 1, 16) to (start + 0, 21) - = (((c1 + c3) + (c4 + c5)) - c6) +- Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 14) + = ((c3 + c5) - c6) +- Code(Expression(2, Add)) at (prev + 0, 18) to (start + 0, 23) + = (c3 + c5) +- Code(Expression(0, Sub)) at (prev + 1, 16) to (start + 0, 21) + = ((c3 + c5) - c6) - Code(Zero) at (prev + 0, 22) to (start + 1, 14) -- Code(Expression(41, Sub)) at (prev + 2, 20) to (start + 0, 25) - = ((((c1 + c3) + (c4 + c5)) - c6) - c4) +- Code(Expression(0, Sub)) at (prev + 2, 20) to (start + 0, 25) + = ((c3 + c5) - c6) - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) -- Code(Expression(40, Sub)) at (prev + 1, 18) to (start + 0, 19) - = (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7) -- Code(Expression(40, Sub)) at (prev + 1, 17) to (start + 0, 34) - = (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7) -- Code(Expression(39, Sub)) at (prev + 0, 34) to (start + 0, 35) - = ((((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7) - c5) +- Code(Expression(0, Sub)) at (prev + 1, 18) to (start + 0, 19) + = ((c3 + c5) - c6) +- Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 34) + = ((c3 + c5) - c6) +- Code(Expression(5, Sub)) at (prev + 0, 34) to (start + 0, 35) + = (((c3 + c5) - c6) - c5) - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) -- Code(Expression(38, Add)) at (prev + 1, 5) to (start + 0, 6) - = (((((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7) - c5) + (c6 + c9)) +- Code(Expression(4, Add)) at (prev + 1, 5) to (start + 0, 6) + = ((((c3 + c5) - c6) - c5) + (c6 + c9)) Function name: loops_branches::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 38, 01, 05, 02] diff --git a/tests/coverage-map/status-quo/unused.cov-map b/tests/coverage-map/status-quo/unused.cov-map index 84bbb2c262b06..5d58ebb6d1c58 100644 --- a/tests/coverage-map/status-quo/unused.cov-map +++ b/tests/coverage-map/status-quo/unused.cov-map @@ -47,45 +47,45 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 35, 1) to (start + 4, 2) Function name: unused::unused_func (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 01, 11, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 11, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 17, 1) to (start + 1, 14) +- Code(Zero) at (prev + 17, 1) to (start + 1, 14) - Code(Zero) at (prev + 1, 15) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Function name: unused::unused_func2 (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 01, 17, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 17, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 23, 1) to (start + 1, 14) +- Code(Zero) at (prev + 23, 1) to (start + 1, 14) - Code(Zero) at (prev + 1, 15) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Function name: unused::unused_func3 (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 01, 1d, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 1d, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 29, 1) to (start + 1, 14) +- Code(Zero) at (prev + 29, 1) to (start + 1, 14) - Code(Zero) at (prev + 1, 15) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Function name: unused::unused_template_func::<_> (unused) -Raw bytes (34): 0x[01, 01, 00, 06, 01, 09, 01, 01, 12, 00, 02, 0b, 00, 11, 00, 01, 09, 00, 0f, 00, 00, 13, 00, 19, 00, 01, 09, 00, 0f, 00, 02, 01, 00, 02] +Raw bytes (34): 0x[01, 01, 00, 06, 00, 09, 01, 01, 12, 00, 02, 0b, 00, 11, 00, 01, 09, 00, 0f, 00, 00, 13, 00, 19, 00, 01, 09, 00, 0f, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 9, 1) to (start + 1, 18) +- Code(Zero) at (prev + 9, 1) to (start + 1, 18) - Code(Zero) at (prev + 2, 11) to (start + 0, 17) - Code(Zero) at (prev + 1, 9) to (start + 0, 15) - Code(Zero) at (prev + 0, 19) to (start + 0, 25)