From cc832c5de53090a8d25da0f2043177ee8d6048b4 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 11 Aug 2023 11:52:37 +1000 Subject: [PATCH 1/7] =?UTF-8?q?=F0=9F=8D=92=20Add=20tool=20`src/tools/cove?= =?UTF-8?q?rage-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 2/7] =?UTF-8?q?=F0=9F=8D=92=20Add=20test=20suite=20`covera?= =?UTF-8?q?ge-map`=20to=20test=20coverage=20mappings=20emitted=20by=20LLVM?= 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 3/7] =?UTF-8?q?=F0=9F=8D=92=20Copy=20a=20selection=20of=20?= =?UTF-8?q?`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 4/7] 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 5/7] 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 6/7] 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 7/7] 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]