From fdc931899d837b2dbf3d373848c50a201303193c Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 9 Jan 2020 18:36:55 +0100 Subject: [PATCH 1/2] Remove unused argument --- src/tools/compiletest/src/main.rs | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index a61b940398704..028483b7d95b5 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -449,15 +449,8 @@ pub fn test_opts(config: &Config) -> test::TestOpts { pub fn make_tests(config: &Config, tests: &mut Vec) { debug!("making tests from {:?}", config.src_base.display()); let inputs = common_inputs_stamp(config); - collect_tests_from_dir( - config, - &config.src_base, - &config.src_base, - &PathBuf::new(), - &inputs, - tests, - ) - .expect(&format!("Could not read tests from {}", config.src_base.display())); + collect_tests_from_dir(config, &config.src_base, &PathBuf::new(), &inputs, tests) + .expect(&format!("Could not read tests from {}", config.src_base.display())); } /// Returns a stamp constructed from input files common to all test cases. @@ -494,7 +487,6 @@ fn common_inputs_stamp(config: &Config) -> Stamp { fn collect_tests_from_dir( config: &Config, - base: &Path, dir: &Path, relative_dir_path: &Path, inputs: &Stamp, @@ -538,14 +530,7 @@ fn collect_tests_from_dir( let relative_file_path = relative_dir_path.join(file.file_name()); if &file_name != "auxiliary" { debug!("found directory: {:?}", file_path.display()); - collect_tests_from_dir( - config, - base, - &file_path, - &relative_file_path, - inputs, - tests, - )?; + collect_tests_from_dir(config, &file_path, &relative_file_path, inputs, tests)?; } } else { debug!("found other file/directory: {:?}", file_path.display()); From c9a5a03ffda14aaf505015b3b866c5a9f3cc6bf4 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 11 Mar 2020 11:49:00 +0100 Subject: [PATCH 2/2] Enable `--bless`ing of MIR dumps --- src/librustc_data_structures/sorted_map.rs | 4 +- src/librustc_mir/interpret/memory.rs | 96 ++---- src/librustc_mir/util/pretty.rs | 282 ++++++++++++++++-- src/test/mir-opt/README.md | 42 ++- src/test/mir-opt/basic_assignment.rs | 34 +-- .../rustc.main.SimplifyCfg-initial.after.mir | 90 ++++++ .../mir-opt/const-promotion-extern-static.rs | 66 +--- .../rustc.BAR-promoted[0].ConstProp.after.mir | 26 ++ .../rustc.BAR.PromoteTemps.diff | 62 ++++ .../rustc.FOO-promoted[0].ConstProp.after.mir | 26 ++ .../rustc.FOO.PromoteTemps.diff | 62 ++++ src/test/mir-opt/const_allocation.rs | 9 + .../32bit/rustc.main.ConstProp.after.mir | 65 ++++ .../64bit/rustc.main.ConstProp.after.mir | 69 +++++ src/test/mir-opt/const_allocation2.rs | 11 + .../32bit/rustc.main.ConstProp.after.mir | 64 ++++ .../64bit/rustc.main.ConstProp.after.mir | 67 +++++ src/test/mir-opt/const_allocation3.rs | 29 ++ .../32bit/rustc.main.ConstProp.after.mir | 58 ++++ .../64bit/rustc.main.ConstProp.after.mir | 59 ++++ src/test/mir-opt/const_prop/cast.rs | 46 +-- .../const_prop/cast/rustc.main.ConstProp.diff | 48 +++ src/tools/compiletest/src/runtest.rs | 139 +++++++-- 23 files changed, 1198 insertions(+), 256 deletions(-) create mode 100644 src/test/mir-opt/basic_assignment/rustc.main.SimplifyCfg-initial.after.mir create mode 100644 src/test/mir-opt/const-promotion-extern-static/rustc.BAR-promoted[0].ConstProp.after.mir create mode 100644 src/test/mir-opt/const-promotion-extern-static/rustc.BAR.PromoteTemps.diff create mode 100644 src/test/mir-opt/const-promotion-extern-static/rustc.FOO-promoted[0].ConstProp.after.mir create mode 100644 src/test/mir-opt/const-promotion-extern-static/rustc.FOO.PromoteTemps.diff create mode 100644 src/test/mir-opt/const_allocation.rs create mode 100644 src/test/mir-opt/const_allocation/32bit/rustc.main.ConstProp.after.mir create mode 100644 src/test/mir-opt/const_allocation/64bit/rustc.main.ConstProp.after.mir create mode 100644 src/test/mir-opt/const_allocation2.rs create mode 100644 src/test/mir-opt/const_allocation2/32bit/rustc.main.ConstProp.after.mir create mode 100644 src/test/mir-opt/const_allocation2/64bit/rustc.main.ConstProp.after.mir create mode 100644 src/test/mir-opt/const_allocation3.rs create mode 100644 src/test/mir-opt/const_allocation3/32bit/rustc.main.ConstProp.after.mir create mode 100644 src/test/mir-opt/const_allocation3/64bit/rustc.main.ConstProp.after.mir create mode 100644 src/test/mir-opt/const_prop/cast/rustc.main.ConstProp.diff diff --git a/src/librustc_data_structures/sorted_map.rs b/src/librustc_data_structures/sorted_map.rs index 8c42b74b85aef..652268dcee884 100644 --- a/src/librustc_data_structures/sorted_map.rs +++ b/src/librustc_data_structures/sorted_map.rs @@ -110,13 +110,13 @@ impl SortedMap { /// Iterate over the keys, sorted #[inline] - pub fn keys(&self) -> impl Iterator + ExactSizeIterator { + pub fn keys(&self) -> impl Iterator + ExactSizeIterator + DoubleEndedIterator { self.data.iter().map(|&(ref k, _)| k) } /// Iterate over values, sorted by key #[inline] - pub fn values(&self) -> impl Iterator + ExactSizeIterator { + pub fn values(&self) -> impl Iterator + ExactSizeIterator + DoubleEndedIterator { self.data.iter().map(|&(_, ref v)| v) } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 8437399752e29..df66ab3f419da 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -649,58 +649,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { &self, allocs_seen: &mut FxHashSet, allocs_to_print: &mut VecDeque, - mut msg: String, alloc: &Allocation, - extra: String, ) { - use std::fmt::Write; - - let prefix_len = msg.len(); - let mut relocations = vec![]; - - for i in 0..alloc.size.bytes() { - let i = Size::from_bytes(i); - if let Some(&(_, target_id)) = alloc.relocations().get(&i) { - if allocs_seen.insert(target_id) { - allocs_to_print.push_back(target_id); - } - relocations.push((i, target_id)); - } - if alloc.undef_mask().is_range_defined(i, i + Size::from_bytes(1)).is_ok() { - // this `as usize` is fine, since `i` came from a `usize` - let i = i.bytes_usize(); - - // Checked definedness (and thus range) and relocations. This access also doesn't - // influence interpreter execution but is only for debugging. - let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(i..i + 1); - write!(msg, "{:02x} ", bytes[0]).unwrap(); - } else { - msg.push_str("__ "); + for &(_, (_, target_id)) in alloc.relocations().iter() { + if allocs_seen.insert(target_id) { + allocs_to_print.push_back(target_id); } } - - eprintln!( - "{}({} bytes, alignment {}){}", - msg, - alloc.size.bytes(), - alloc.align.bytes(), - extra - ); - - if !relocations.is_empty() { - msg.clear(); - write!(msg, "{:1$}", "", prefix_len).unwrap(); // Print spaces. - let mut pos = Size::ZERO; - let relocation_width = (self.pointer_size().bytes() - 1) * 3; - for (i, target_id) in relocations { - write!(msg, "{:1$}", "", ((i - pos) * 3).bytes_usize()).unwrap(); - let target = format!("({})", target_id); - // this `as usize` is fine, since we can't print more chars than `usize::MAX` - write!(msg, "└{0:─^1$}┘ ", target, relocation_width as usize).unwrap(); - pos = i + self.pointer_size(); - } - eprintln!("{}", msg); - } + crate::util::pretty::write_allocation(self.tcx.tcx, alloc, &mut std::io::stderr(), "") + .unwrap(); } /// Print a list of allocations and all allocations they point to, recursively. @@ -713,45 +670,42 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let mut allocs_seen = FxHashSet::default(); while let Some(id) = allocs_to_print.pop_front() { - let msg = format!("Alloc {:<5} ", format!("{}:", id)); + eprint!("Alloc {:<5}: ", id); + fn msg(alloc: &Allocation, extra: &str) { + eprintln!( + "({} bytes, alignment {}){}", + alloc.size.bytes(), + alloc.align.bytes(), + extra + ) + }; // normal alloc? match self.alloc_map.get_or(id, || Err(())) { Ok((kind, alloc)) => { - let extra = match kind { - MemoryKind::Stack => " (stack)".to_owned(), - MemoryKind::Vtable => " (vtable)".to_owned(), - MemoryKind::CallerLocation => " (caller_location)".to_owned(), - MemoryKind::Machine(m) => format!(" ({:?})", m), + match kind { + MemoryKind::Stack => msg(alloc, " (stack)"), + MemoryKind::Vtable => msg(alloc, " (vtable)"), + MemoryKind::CallerLocation => msg(alloc, " (caller_location)"), + MemoryKind::Machine(m) => msg(alloc, &format!(" ({:?})", m)), }; - self.dump_alloc_helper( - &mut allocs_seen, - &mut allocs_to_print, - msg, - alloc, - extra, - ); + self.dump_alloc_helper(&mut allocs_seen, &mut allocs_to_print, alloc); } Err(()) => { // global alloc? match self.tcx.alloc_map.lock().get(id) { Some(GlobalAlloc::Memory(alloc)) => { - self.dump_alloc_helper( - &mut allocs_seen, - &mut allocs_to_print, - msg, - alloc, - " (immutable)".to_owned(), - ); + msg(alloc, " (immutable)"); + self.dump_alloc_helper(&mut allocs_seen, &mut allocs_to_print, alloc); } Some(GlobalAlloc::Function(func)) => { - eprintln!("{} {}", msg, func); + eprintln!("{}", func); } Some(GlobalAlloc::Static(did)) => { - eprintln!("{} {:?}", msg, did); + eprintln!("{:?}", did); } None => { - eprintln!("{} (deallocated)", msg); + eprintln!("(deallocated)"); } } } diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 4c380d1141806..0368a73832d75 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -1,11 +1,14 @@ use super::graphviz::write_mir_fn_graphviz; use crate::transform::MirSource; +use either::Either; +use rustc::mir::interpret::{read_target_uint, AllocId, Allocation, ConstValue, GlobalAlloc}; use rustc::mir::visit::Visitor; use rustc::mir::*; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, layout::Size, TyCtxt, TypeFoldable, TypeVisitor}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_index::vec::Idx; +use std::collections::BTreeSet; use std::fmt::Display; use std::fmt::Write as _; use std::fs; @@ -77,20 +80,7 @@ pub fn dump_mir<'tcx, F>( return; } - let node_path = ty::print::with_forced_impl_filename_line(|| { - // see notes on #41697 below - tcx.def_path_str(source.def_id()) - }); - dump_matched_mir_node( - tcx, - pass_num, - pass_name, - &node_path, - disambiguator, - source, - body, - extra_data, - ); + dump_matched_mir_node(tcx, pass_num, pass_name, disambiguator, source, body, extra_data); } pub fn dump_enabled<'tcx>(tcx: TyCtxt<'tcx>, pass_name: &str, source: MirSource<'tcx>) -> bool { @@ -117,7 +107,6 @@ fn dump_matched_mir_node<'tcx, F>( tcx: TyCtxt<'tcx>, pass_num: Option<&dyn Display>, pass_name: &str, - node_path: &str, disambiguator: &dyn Display, source: MirSource<'tcx>, body: &Body<'tcx>, @@ -127,10 +116,16 @@ fn dump_matched_mir_node<'tcx, F>( { let _: io::Result<()> = try { let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, source)?; - writeln!(file, "// MIR for `{}`", node_path)?; - writeln!(file, "// source = {:?}", source)?; - writeln!(file, "// pass_name = {}", pass_name)?; - writeln!(file, "// disambiguator = {}", disambiguator)?; + let def_path = ty::print::with_forced_impl_filename_line(|| { + // see notes on #41697 above + tcx.def_path_str(source.def_id()) + }); + write!(file, "// MIR for `{}", def_path)?; + match source.promoted { + None => write!(file, "`")?, + Some(promoted) => write!(file, "::{:?}`", promoted)?, + } + writeln!(file, " {} {}", disambiguator, pass_name)?; if let Some(ref layout) = body.generator_layout { writeln!(file, "// generator_layout = {:?}", layout)?; } @@ -276,6 +271,9 @@ where } writeln!(w, "}}")?; + + write_allocations(tcx, body, w)?; + Ok(()) } @@ -534,6 +532,250 @@ pub fn write_mir_intro<'tcx>( Ok(()) } +/// Find all `AllocId`s mentioned (recursively) in the MIR body and print their corresponding +/// allocations. +pub fn write_allocations<'tcx>( + tcx: TyCtxt<'tcx>, + body: &Body<'_>, + w: &mut dyn Write, +) -> io::Result<()> { + fn alloc_ids_from_alloc(alloc: &Allocation) -> impl DoubleEndedIterator + '_ { + alloc.relocations().values().map(|(_, id)| *id) + } + fn alloc_ids_from_const(val: ConstValue<'_>) -> impl Iterator + '_ { + match val { + ConstValue::Scalar(interpret::Scalar::Ptr(ptr)) => { + Either::Left(Either::Left(std::iter::once(ptr.alloc_id))) + } + ConstValue::Scalar(interpret::Scalar::Raw { .. }) => { + Either::Left(Either::Right(std::iter::empty())) + } + ConstValue::ByRef { alloc, .. } | ConstValue::Slice { data: alloc, .. } => { + Either::Right(alloc_ids_from_alloc(alloc)) + } + } + } + struct CollectAllocIds(BTreeSet); + impl<'tcx> TypeVisitor<'tcx> for CollectAllocIds { + fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool { + if let ty::ConstKind::Value(val) = c.val { + self.0.extend(alloc_ids_from_const(val)); + } + c.super_visit_with(self) + } + } + let mut visitor = CollectAllocIds(Default::default()); + body.visit_with(&mut visitor); + let mut seen = visitor.0; + let mut todo: Vec<_> = seen.iter().copied().collect(); + while let Some(id) = todo.pop() { + let mut write_header_and_allocation = + |w: &mut dyn Write, alloc: &Allocation| -> io::Result<()> { + write!(w, "size: {}, align: {})", alloc.size.bytes(), alloc.align.bytes())?; + if alloc.size == Size::ZERO { + write!(w, " {{}}")?; + } else { + writeln!(w, " {{")?; + write_allocation(tcx, alloc, w, " ")?; + write!(w, "}}")?; + // `.rev()` because we are popping them from the back of the `todo` vector. + for id in alloc_ids_from_alloc(alloc).rev() { + if seen.insert(id) { + todo.push(id); + } + } + } + Ok(()) + }; + write!(w, "\n{}", id)?; + let alloc = tcx.alloc_map.lock().get(id); + match alloc { + // This can't really happen unless there are bugs, but it doesn't cost us anything to + // gracefully handle it and allow buggy rustc to be debugged via allocation printing. + None => write!(w, " (deallocated)")?, + Some(GlobalAlloc::Function(inst)) => write!(w, " (fn: {})", inst)?, + Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => { + match tcx.const_eval_poly(did) { + Ok(ConstValue::ByRef { alloc, .. }) => { + write!(w, " (static: {}, ", tcx.def_path_str(did))?; + write_header_and_allocation(w, alloc)?; + } + Ok(_) => { + span_bug!(tcx.def_span(did), " static item without `ByRef` initializer") + } + Err(_) => write!( + w, + " (static: {}, error during initializer evaluation)", + tcx.def_path_str(did) + )?, + } + } + Some(GlobalAlloc::Static(did)) => { + write!(w, " (extern static: {})", tcx.def_path_str(did))? + } + Some(GlobalAlloc::Memory(alloc)) => { + write!(w, " (")?; + write_header_and_allocation(w, alloc)? + } + } + + writeln!(w)?; + } + Ok(()) +} + +fn write_allocation_endline(w: &mut dyn Write, ascii: &str) -> io::Result<()> { + for _ in 0..(BYTES_PER_LINE - ascii.chars().count()) { + write!(w, " ")?; + } + writeln!(w, " │ {}", ascii) +} + +/// Number of bytes to print per allocation hex dump line. +const BYTES_PER_LINE: usize = 16; + +/// Prints the line start address and returns the new line start address. +fn write_allocation_newline( + w: &mut dyn Write, + mut line_start: Size, + ascii: &str, + pos_width: usize, + prefix: &str, +) -> io::Result { + write_allocation_endline(w, ascii)?; + line_start += Size::from_bytes(BYTES_PER_LINE); + write!(w, "{}0x{:02$x} │ ", prefix, line_start.bytes(), pos_width)?; + Ok(line_start) +} + +/// Dumps the bytes of an allocation to the given writer. This also prints relocations instead of +/// the raw bytes where applicable. +/// The byte format is similar to how hex editors print bytes. Each line starts with the address of +/// the start of the line, followed by all bytes in hex format (space separated). +/// If the allocation is small enough to fit into a single line, no start address is given. +/// After the hex dump, an ascii dump follows, replacing all unprintable characters (control +/// characters or characters whose value is larger than 127) with a `.` +/// +/// The `prefix` argument allows callers to add an arbitrary prefix before each line (even if there +/// is only one line). Note that your prefix should contain a trailing space as the lines are +/// printed directly after it. +pub fn write_allocation( + tcx: TyCtxt<'tcx>, + alloc: &Allocation, + w: &mut dyn Write, + prefix: &str, +) -> io::Result<()> { + let num_lines = alloc.size.bytes_usize().saturating_sub(BYTES_PER_LINE); + // Number of chars needed to represent all line numbers. + let pos_width = format!("{:x}", alloc.size.bytes()).len(); + + if num_lines > 0 { + write!(w, "{}0x{:02$x} │ ", prefix, 0, pos_width)?; + } else { + write!(w, "{}", prefix)?; + } + + let mut i = Size::ZERO; + let mut line_start = Size::ZERO; + + let ptr_size = tcx.data_layout.pointer_size; + + let mut ascii = String::new(); + + let oversized_ptr = |target: &mut String, width| { + if target.len() > width { + write!(target, " ({} ptr bytes)", ptr_size.bytes()).unwrap(); + } + }; + + while i < alloc.size { + // The line start already has a space. While we could remove that space from the line start + // printing and unconditionally print a space here, that would cause the single-line case + // to have a single space before it, which looks weird. + if i != line_start { + write!(w, " ")?; + } + if let Some(&(_, target_id)) = alloc.relocations().get(&i) { + // Memory with a relocation must be defined + let j = i.bytes_usize(); + let offset = + alloc.inspect_with_undef_and_ptr_outside_interpreter(j..j + ptr_size.bytes_usize()); + let offset = read_target_uint(tcx.data_layout.endian, offset).unwrap(); + let relocation_width = |bytes| bytes * 3; + let mut target = format!("{}+{}", target_id, offset); + if ((i - line_start) + ptr_size).bytes_usize() > BYTES_PER_LINE { + // This branch handles the situation where a relocation starts in the current line + // but ends in the next one. + let remainder = Size::from_bytes(BYTES_PER_LINE) - (i - line_start); + let overflow = ptr_size - remainder; + let remainder_width = relocation_width(remainder.bytes_usize()) - 2; + let overflow_width = relocation_width(overflow.bytes_usize() - 1) + 1; + ascii.push('╾'); + for _ in 0..remainder.bytes() - 1 { + ascii.push('─'); + } + if overflow_width > remainder_width && overflow_width >= target.len() { + // The case where the relocation fits into the part in the next line + write!(w, "╾{0:─^1$}", "", remainder_width)?; + line_start = + write_allocation_newline(w, line_start, &ascii, pos_width, prefix)?; + ascii.clear(); + write!(w, "{0:─^1$}╼", target, overflow_width)?; + } else { + oversized_ptr(&mut target, remainder_width); + write!(w, "╾{0:─^1$}", target, remainder_width)?; + line_start = + write_allocation_newline(w, line_start, &ascii, pos_width, prefix)?; + write!(w, "{0:─^1$}╼", "", overflow_width)?; + ascii.clear(); + } + for _ in 0..overflow.bytes() - 1 { + ascii.push('─'); + } + ascii.push('╼'); + i += ptr_size; + continue; + } else { + // This branch handles a relocation that starts and ends in the current line. + let relocation_width = relocation_width(ptr_size.bytes_usize() - 1); + oversized_ptr(&mut target, relocation_width); + ascii.push('╾'); + write!(w, "╾{0:─^1$}╼", target, relocation_width)?; + for _ in 0..ptr_size.bytes() - 2 { + ascii.push('─'); + } + ascii.push('╼'); + i += ptr_size; + } + } else if alloc.undef_mask().is_range_defined(i, i + Size::from_bytes(1)).is_ok() { + let j = i.bytes_usize(); + + // Checked definedness (and thus range) and relocations. This access also doesn't + // influence interpreter execution but is only for debugging. + let c = alloc.inspect_with_undef_and_ptr_outside_interpreter(j..j + 1)[0]; + write!(w, "{:02x}", c)?; + if c.is_ascii_control() || c >= 0x80 { + ascii.push('.'); + } else { + ascii.push(char::from(c)); + } + i += Size::from_bytes(1); + } else { + write!(w, "__")?; + ascii.push('░'); + i += Size::from_bytes(1); + } + // Print a new line header if the next line still has some bytes to print. + if i == line_start + Size::from_bytes(BYTES_PER_LINE) && i != alloc.size { + line_start = write_allocation_newline(w, line_start, &ascii, pos_width, prefix)?; + ascii.clear(); + } + } + write_allocation_endline(w, &ascii)?; + + Ok(()) +} + fn write_mir_sig( tcx: TyCtxt<'_>, src: MirSource<'tcx>, diff --git a/src/test/mir-opt/README.md b/src/test/mir-opt/README.md index ad4932b9fb945..a6f86d4e384ae 100644 --- a/src/test/mir-opt/README.md +++ b/src/test/mir-opt/README.md @@ -1,6 +1,46 @@ This folder contains tests for MIR optimizations. -The test format is: +There are two test formats. One allows specifying a pattern to look for in the MIR, which also +permits leaving placeholders, but requires you to manually change the pattern if anything changes. +The other emits MIR to extra files that you can automatically update by specifying `--bless` on +the command line (just like `ui` tests updating `.stderr` files). + +# `--bless`able test format + +By default 32 bit and 64 bit targets use the same dump files, which can be problematic in the +presence of pointers in constants or other bit width dependent things. In that case you can add + +``` +// EMIT_MIR_FOR_EACH_BIT_WIDTH +``` + +to your test, causing separate files to be generated for 32bit and 64bit systems. + +## Emit a diff of the mir for a specific optimization + +This is what you want most often when you want to see how an optimization changes the MIR. + +``` +// EMIT_MIR $file_name_of_some_mir_dump.diff +``` + +## Emit mir after a specific optimization + +Use this if you are just interested in the final state after an optimization. + +``` +// EMIT_MIR $file_name_of_some_mir_dump.after.mir +``` + +## Emit mir before a specific optimization + +This exists mainly for completeness and is rarely useful. + +``` +// EMIT_MIR $file_name_of_some_mir_dump.before.mir +``` + +# Inline test format ``` (arbitrary rust code) diff --git a/src/test/mir-opt/basic_assignment.rs b/src/test/mir-opt/basic_assignment.rs index ca0e9fa811a26..17141b6334c82 100644 --- a/src/test/mir-opt/basic_assignment.rs +++ b/src/test/mir-opt/basic_assignment.rs @@ -1,5 +1,7 @@ // this tests move up progration, which is not yet implemented +// EMIT_MIR rustc.main.SimplifyCfg-initial.after.mir + // Check codegen for assignments (`a = b`) where the left-hand-side is // not yet initialized. Assignments tend to be absent in simple code, // so subtle breakage in them can leave a quite hard-to-find trail of @@ -13,40 +15,10 @@ fn main() { // assignment: nodrop_y = nodrop_x; - let drop_x : Option> = None; + let drop_x: Option> = None; let drop_y; // Since the type of `drop_y` has drop, we generate a `replace` // terminator: drop_y = drop_x; } - -// END RUST SOURCE -// START rustc.main.SimplifyCfg-initial.after.mir -// bb0: { -// StorageLive(_1); -// _1 = const false; -// FakeRead(ForLet, _1); -// StorageLive(_2); -// StorageLive(_3); -// _3 = _1; -// _2 = move _3; -// StorageDead(_3); -// StorageLive(_4); -// _4 = std::option::Option::>::None; -// FakeRead(ForLet, _4); -// AscribeUserType(_4, o, UserTypeProjection { base: UserType(1), projs: [] }); -// StorageLive(_5); -// StorageLive(_6); -// _6 = move _4; -// replace(_5 <- move _6) -> [return: bb2, unwind: bb5]; -// } -// ... -// bb2: { -// drop(_6) -> [return: bb6, unwind: bb4]; -// } -// ... -// bb5 (cleanup): { -// drop(_6) -> bb4; -// } -// END rustc.main.SimplifyCfg-initial.after.mir diff --git a/src/test/mir-opt/basic_assignment/rustc.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/basic_assignment/rustc.main.SimplifyCfg-initial.after.mir new file mode 100644 index 0000000000000..a3f4573964c3d --- /dev/null +++ b/src/test/mir-opt/basic_assignment/rustc.main.SimplifyCfg-initial.after.mir @@ -0,0 +1,90 @@ +// MIR for `main` after SimplifyCfg-initial + +| User Type Annotations +| 0: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option>) } at $DIR/basic_assignment.rs:18:17: 18:33 +| 1: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option>) } at $DIR/basic_assignment.rs:18:17: 18:33 +| +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/basic_assignment.rs:10:11: 10:11 + let _1: bool; // in scope 0 at $DIR/basic_assignment.rs:11:9: 11:17 + let mut _3: bool; // in scope 0 at $DIR/basic_assignment.rs:16:16: 16:24 + let mut _6: std::option::Option>; // in scope 0 at $DIR/basic_assignment.rs:23:14: 23:20 + scope 1 { + debug nodrop_x => _1; // in scope 1 at $DIR/basic_assignment.rs:11:9: 11:17 + let _2: bool; // in scope 1 at $DIR/basic_assignment.rs:12:9: 12:17 + scope 2 { + debug nodrop_y => _2; // in scope 2 at $DIR/basic_assignment.rs:12:9: 12:17 + let _4: std::option::Option> as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 2 at $DIR/basic_assignment.rs:18:9: 18:15 + scope 3 { + debug drop_x => _4; // in scope 3 at $DIR/basic_assignment.rs:18:9: 18:15 + let _5: std::option::Option>; // in scope 3 at $DIR/basic_assignment.rs:19:9: 19:15 + scope 4 { + debug drop_y => _5; // in scope 4 at $DIR/basic_assignment.rs:19:9: 19:15 + } + } + } + } + + bb0: { + StorageLive(_1); // bb0[0]: scope 0 at $DIR/basic_assignment.rs:11:9: 11:17 + _1 = const false; // bb0[1]: scope 0 at $DIR/basic_assignment.rs:11:20: 11:25 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x00)) + // mir::Constant + // + span: $DIR/basic_assignment.rs:11:20: 11:25 + // + literal: Const { ty: bool, val: Value(Scalar(0x00)) } + FakeRead(ForLet, _1); // bb0[2]: scope 0 at $DIR/basic_assignment.rs:11:9: 11:17 + StorageLive(_2); // bb0[3]: scope 1 at $DIR/basic_assignment.rs:12:9: 12:17 + StorageLive(_3); // bb0[4]: scope 2 at $DIR/basic_assignment.rs:16:16: 16:24 + _3 = _1; // bb0[5]: scope 2 at $DIR/basic_assignment.rs:16:16: 16:24 + _2 = move _3; // bb0[6]: scope 2 at $DIR/basic_assignment.rs:16:5: 16:24 + StorageDead(_3); // bb0[7]: scope 2 at $DIR/basic_assignment.rs:16:23: 16:24 + StorageLive(_4); // bb0[8]: scope 2 at $DIR/basic_assignment.rs:18:9: 18:15 + _4 = std::option::Option::>::None; // bb0[9]: scope 2 at $DIR/basic_assignment.rs:18:36: 18:40 + FakeRead(ForLet, _4); // bb0[10]: scope 2 at $DIR/basic_assignment.rs:18:9: 18:15 + AscribeUserType(_4, o, UserTypeProjection { base: UserType(1), projs: [] }); // bb0[11]: scope 2 at $DIR/basic_assignment.rs:18:17: 18:33 + StorageLive(_5); // bb0[12]: scope 3 at $DIR/basic_assignment.rs:19:9: 19:15 + StorageLive(_6); // bb0[13]: scope 4 at $DIR/basic_assignment.rs:23:14: 23:20 + _6 = move _4; // bb0[14]: scope 4 at $DIR/basic_assignment.rs:23:14: 23:20 + replace(_5 <- move _6) -> [return: bb2, unwind: bb5]; // bb0[15]: scope 4 at $DIR/basic_assignment.rs:23:5: 23:11 + } + + bb1 (cleanup): { + resume; // bb1[0]: scope 0 at $DIR/basic_assignment.rs:10:1: 24:2 + } + + bb2: { + drop(_6) -> [return: bb6, unwind: bb4]; // bb2[0]: scope 4 at $DIR/basic_assignment.rs:23:19: 23:20 + } + + bb3 (cleanup): { + drop(_4) -> bb1; // bb3[0]: scope 2 at $DIR/basic_assignment.rs:24:1: 24:2 + } + + bb4 (cleanup): { + drop(_5) -> bb3; // bb4[0]: scope 3 at $DIR/basic_assignment.rs:24:1: 24:2 + } + + bb5 (cleanup): { + drop(_6) -> bb4; // bb5[0]: scope 4 at $DIR/basic_assignment.rs:23:19: 23:20 + } + + bb6: { + StorageDead(_6); // bb6[0]: scope 4 at $DIR/basic_assignment.rs:23:19: 23:20 + _0 = (); // bb6[1]: scope 0 at $DIR/basic_assignment.rs:10:11: 24:2 + drop(_5) -> [return: bb7, unwind: bb3]; // bb6[2]: scope 3 at $DIR/basic_assignment.rs:24:1: 24:2 + } + + bb7: { + StorageDead(_5); // bb7[0]: scope 3 at $DIR/basic_assignment.rs:24:1: 24:2 + drop(_4) -> [return: bb8, unwind: bb1]; // bb7[1]: scope 2 at $DIR/basic_assignment.rs:24:1: 24:2 + } + + bb8: { + StorageDead(_4); // bb8[0]: scope 2 at $DIR/basic_assignment.rs:24:1: 24:2 + StorageDead(_2); // bb8[1]: scope 1 at $DIR/basic_assignment.rs:24:1: 24:2 + StorageDead(_1); // bb8[2]: scope 0 at $DIR/basic_assignment.rs:24:1: 24:2 + return; // bb8[3]: scope 0 at $DIR/basic_assignment.rs:24:2: 24:2 + } +} diff --git a/src/test/mir-opt/const-promotion-extern-static.rs b/src/test/mir-opt/const-promotion-extern-static.rs index c858a4c5ee7c6..c9d350a98fd9c 100644 --- a/src/test/mir-opt/const-promotion-extern-static.rs +++ b/src/test/mir-opt/const-promotion-extern-static.rs @@ -4,70 +4,12 @@ extern "C" { static Y: i32 = 42; +// EMIT_MIR rustc.BAR.PromoteTemps.diff +// EMIT_MIR rustc.BAR-promoted[0].ConstProp.after.mir static mut BAR: *const &i32 = [&Y].as_ptr(); +// EMIT_MIR rustc.FOO.PromoteTemps.diff +// EMIT_MIR rustc.FOO-promoted[0].ConstProp.after.mir static mut FOO: *const &i32 = [unsafe { &X }].as_ptr(); fn main() {} - -// END RUST SOURCE -// START rustc.FOO.PromoteTemps.before.mir -// bb0: { -// ... -// _5 = const {alloc1+0: &i32}; -// _4 = &(*_5); -// _3 = [move _4]; -// _2 = &_3; -// _1 = move _2 as &[&i32] (Pointer(Unsize)); -// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; -// } -// ... -// bb2: { -// StorageDead(_5); -// StorageDead(_3); -// return; -// } -// END rustc.FOO.PromoteTemps.before.mir -// START rustc.BAR.PromoteTemps.before.mir -// bb0: { -// ... -// _5 = const {alloc0+0: &i32}; -// _4 = &(*_5); -// _3 = [move _4]; -// _2 = &_3; -// _1 = move _2 as &[&i32] (Pointer(Unsize)); -// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; -// } -// ... -// bb2: { -// StorageDead(_5); -// StorageDead(_3); -// return; -// } -// END rustc.BAR.PromoteTemps.before.mir -// START rustc.BAR.PromoteTemps.after.mir -// bb0: { -// ... -// _6 = const BAR::promoted[0]; -// _2 = &(*_6); -// _1 = move _2 as &[&i32] (Pointer(Unsize)); -// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; -// } -// ... -// bb2: { -// return; -// } -// END rustc.BAR.PromoteTemps.after.mir -// START rustc.FOO.PromoteTemps.after.mir -// bb0: { -// ... -// _6 = const FOO::promoted[0]; -// _2 = &(*_6); -// _1 = move _2 as &[&i32] (Pointer(Unsize)); -// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; -// } -// ... -// bb2: { -// return; -// } -// END rustc.FOO.PromoteTemps.after.mir diff --git a/src/test/mir-opt/const-promotion-extern-static/rustc.BAR-promoted[0].ConstProp.after.mir b/src/test/mir-opt/const-promotion-extern-static/rustc.BAR-promoted[0].ConstProp.after.mir new file mode 100644 index 0000000000000..256018adaa89b --- /dev/null +++ b/src/test/mir-opt/const-promotion-extern-static/rustc.BAR-promoted[0].ConstProp.after.mir @@ -0,0 +1,26 @@ +// MIR for `BAR::promoted[0]` after ConstProp + +promoted[0] in BAR: &[&i32; 1] = { + let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + let mut _1: [&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + let mut _2: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 + let mut _3: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 + + bb0: { + _3 = const {alloc0+0: &i32}; // bb0[0]: scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 + // ty::Const + // + ty: &i32 + // + val: Value(Scalar(alloc0+0)) + // mir::Constant + // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34 + // + literal: Const { ty: &i32, val: Value(Scalar(alloc0+0)) } + _2 = _3; // bb0[1]: scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 + _1 = [move _2]; // bb0[2]: scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + _0 = &_1; // bb0[3]: scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + return; // bb0[4]: scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + } +} + +alloc0 (static: Y, size: 4, align: 4) { + 2a 00 00 00 │ *... +} diff --git a/src/test/mir-opt/const-promotion-extern-static/rustc.BAR.PromoteTemps.diff b/src/test/mir-opt/const-promotion-extern-static/rustc.BAR.PromoteTemps.diff new file mode 100644 index 0000000000000..bc5b114418e42 --- /dev/null +++ b/src/test/mir-opt/const-promotion-extern-static/rustc.BAR.PromoteTemps.diff @@ -0,0 +1,62 @@ +- // MIR for `BAR` before PromoteTemps ++ // MIR for `BAR` after PromoteTemps + + static mut BAR: *const &i32 = { + let mut _0: *const &i32; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:9:17: 9:28 + let mut _1: &[&i32]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + let mut _2: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + let _3: [&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + let mut _4: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 + let _5: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 ++ let mut _6: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + + bb0: { + StorageLive(_1); // bb0[0]: scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + StorageLive(_2); // bb0[1]: scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 +- StorageLive(_3); // bb0[2]: scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 +- StorageLive(_4); // bb0[3]: scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 +- StorageLive(_5); // bb0[4]: scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 +- _5 = const {alloc0+0: &i32}; // bb0[5]: scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 ++ _6 = const BAR::promoted[0]; // bb0[2]: scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + // ty::Const +- // + ty: &i32 +- // + val: Value(Scalar(alloc0+0)) ++ // + ty: &[&i32; 1] ++ // + val: Unevaluated(DefId(0:6 ~ const_promotion_extern_static[317d]::BAR[0]), [], Some(promoted[0])) + // mir::Constant +- // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34 +- // + literal: Const { ty: &i32, val: Value(Scalar(alloc0+0)) } +- _4 = &(*_5); // bb0[6]: scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 +- _3 = [move _4]; // bb0[7]: scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 +- _2 = &_3; // bb0[8]: scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 +- _1 = move _2 as &[&i32] (Pointer(Unsize)); // bb0[9]: scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 +- _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // bb0[10]: scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 ++ // + span: $DIR/const-promotion-extern-static.rs:9:31: 9:35 ++ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(DefId(0:6 ~ const_promotion_extern_static[317d]::BAR[0]), [], Some(promoted[0])) } ++ _2 = &(*_6); // bb0[3]: scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 ++ _1 = move _2 as &[&i32] (Pointer(Unsize)); // bb0[4]: scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 ++ _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // bb0[5]: scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 + // ty::Const + // + ty: for<'r> fn(&'r [&i32]) -> *const &i32 {core::slice::::as_ptr} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/const-promotion-extern-static.rs:9:36: 9:42 + // + literal: Const { ty: for<'r> fn(&'r [&i32]) -> *const &i32 {core::slice::::as_ptr}, val: Value(Scalar()) } + } + + bb1 (cleanup): { + resume; // bb1[0]: scope 0 at $DIR/const-promotion-extern-static.rs:9:1: 9:45 + } + + bb2: { +- StorageDead(_5); // bb2[0]: scope 0 at $DIR/const-promotion-extern-static.rs:9:43: 9:44 +- StorageDead(_3); // bb2[1]: scope 0 at $DIR/const-promotion-extern-static.rs:9:43: 9:44 +- return; // bb2[2]: scope 0 at $DIR/const-promotion-extern-static.rs:9:1: 9:45 ++ return; // bb2[0]: scope 0 at $DIR/const-promotion-extern-static.rs:9:1: 9:45 + } +- } +- +- alloc0 (static: Y, size: 4, align: 4) { +- 2a 00 00 00 │ *... + } + diff --git a/src/test/mir-opt/const-promotion-extern-static/rustc.FOO-promoted[0].ConstProp.after.mir b/src/test/mir-opt/const-promotion-extern-static/rustc.FOO-promoted[0].ConstProp.after.mir new file mode 100644 index 0000000000000..5bbc05a9cab7c --- /dev/null +++ b/src/test/mir-opt/const-promotion-extern-static/rustc.FOO-promoted[0].ConstProp.after.mir @@ -0,0 +1,26 @@ +// MIR for `FOO::promoted[0]` after ConstProp + +promoted[0] in FOO: &[&i32; 1] = { + let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + let mut _1: [&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + let mut _2: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:32: 13:45 + let mut _3: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 + scope 1 { + } + + bb0: { + _3 = const {alloc2+0: &i32}; // bb0[0]: scope 0 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 + // ty::Const + // + ty: &i32 + // + val: Value(Scalar(alloc2+0)) + // mir::Constant + // + span: $DIR/const-promotion-extern-static.rs:13:42: 13:43 + // + literal: Const { ty: &i32, val: Value(Scalar(alloc2+0)) } + _2 = _3; // bb0[1]: scope 0 at $DIR/const-promotion-extern-static.rs:13:41: 13:43 + _1 = [move _2]; // bb0[2]: scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + _0 = &_1; // bb0[3]: scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + return; // bb0[4]: scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + } +} + +alloc2 (extern static: X) diff --git a/src/test/mir-opt/const-promotion-extern-static/rustc.FOO.PromoteTemps.diff b/src/test/mir-opt/const-promotion-extern-static/rustc.FOO.PromoteTemps.diff new file mode 100644 index 0000000000000..7df1a47b2f497 --- /dev/null +++ b/src/test/mir-opt/const-promotion-extern-static/rustc.FOO.PromoteTemps.diff @@ -0,0 +1,62 @@ +- // MIR for `FOO` before PromoteTemps ++ // MIR for `FOO` after PromoteTemps + + static mut FOO: *const &i32 = { + let mut _0: *const &i32; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:13:17: 13:28 + let mut _1: &[&i32]; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + let mut _2: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + let _3: [&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + let mut _4: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:32: 13:45 + let _5: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 ++ let mut _6: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + scope 1 { + } + + bb0: { + StorageLive(_1); // bb0[0]: scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + StorageLive(_2); // bb0[1]: scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 +- StorageLive(_3); // bb0[2]: scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 +- StorageLive(_4); // bb0[3]: scope 0 at $DIR/const-promotion-extern-static.rs:13:32: 13:45 +- StorageLive(_5); // bb0[4]: scope 1 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 +- _5 = const {alloc2+0: &i32}; // bb0[5]: scope 1 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 ++ _6 = const FOO::promoted[0]; // bb0[2]: scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + // ty::Const +- // + ty: &i32 +- // + val: Value(Scalar(alloc2+0)) ++ // + ty: &[&i32; 1] ++ // + val: Unevaluated(DefId(0:7 ~ const_promotion_extern_static[317d]::FOO[0]), [], Some(promoted[0])) + // mir::Constant +- // + span: $DIR/const-promotion-extern-static.rs:13:42: 13:43 +- // + literal: Const { ty: &i32, val: Value(Scalar(alloc2+0)) } +- _4 = &(*_5); // bb0[6]: scope 1 at $DIR/const-promotion-extern-static.rs:13:41: 13:43 +- _3 = [move _4]; // bb0[7]: scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 +- _2 = &_3; // bb0[8]: scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 +- _1 = move _2 as &[&i32] (Pointer(Unsize)); // bb0[9]: scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 +- _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // bb0[10]: scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 ++ // + span: $DIR/const-promotion-extern-static.rs:13:31: 13:46 ++ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(DefId(0:7 ~ const_promotion_extern_static[317d]::FOO[0]), [], Some(promoted[0])) } ++ _2 = &(*_6); // bb0[3]: scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 ++ _1 = move _2 as &[&i32] (Pointer(Unsize)); // bb0[4]: scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 ++ _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // bb0[5]: scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 + // ty::Const + // + ty: for<'r> fn(&'r [&i32]) -> *const &i32 {core::slice::::as_ptr} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/const-promotion-extern-static.rs:13:47: 13:53 + // + literal: Const { ty: for<'r> fn(&'r [&i32]) -> *const &i32 {core::slice::::as_ptr}, val: Value(Scalar()) } + } + + bb1 (cleanup): { + resume; // bb1[0]: scope 0 at $DIR/const-promotion-extern-static.rs:13:1: 13:56 + } + + bb2: { +- StorageDead(_5); // bb2[0]: scope 0 at $DIR/const-promotion-extern-static.rs:13:54: 13:55 +- StorageDead(_3); // bb2[1]: scope 0 at $DIR/const-promotion-extern-static.rs:13:54: 13:55 +- return; // bb2[2]: scope 0 at $DIR/const-promotion-extern-static.rs:13:1: 13:56 ++ return; // bb2[0]: scope 0 at $DIR/const-promotion-extern-static.rs:13:1: 13:56 + } + } +- +- alloc2 (extern static: X) + diff --git a/src/test/mir-opt/const_allocation.rs b/src/test/mir-opt/const_allocation.rs new file mode 100644 index 0000000000000..aaf996ee8e1a7 --- /dev/null +++ b/src/test/mir-opt/const_allocation.rs @@ -0,0 +1,9 @@ +// EMIT_MIR_FOR_EACH_BIT_WIDTH + +static FOO: &[(Option, &[&str])] = + &[(None, &[]), (None, &["foo", "bar"]), (Some(42), &["meh", "mop", "möp"])]; + +// EMIT_MIR rustc.main.ConstProp.after.mir +fn main() { + FOO; +} diff --git a/src/test/mir-opt/const_allocation/32bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation/32bit/rustc.main.ConstProp.after.mir new file mode 100644 index 0000000000000..5880672450878 --- /dev/null +++ b/src/test/mir-opt/const_allocation/32bit/rustc.main.ConstProp.after.mir @@ -0,0 +1,65 @@ +// MIR for `main` after ConstProp + +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/const_allocation.rs:7:11: 7:11 + let _1: &[(std::option::Option, &[&str])]; // in scope 0 at $DIR/const_allocation.rs:8:5: 8:8 + let mut _2: &&[(std::option::Option, &[&str])]; // in scope 0 at $DIR/const_allocation.rs:8:5: 8:8 + + bb0: { + StorageLive(_1); // bb0[0]: scope 0 at $DIR/const_allocation.rs:8:5: 8:8 + StorageLive(_2); // bb0[1]: scope 0 at $DIR/const_allocation.rs:8:5: 8:8 + _2 = const {alloc0+0: &&[(std::option::Option, &[&str])]}; // bb0[2]: scope 0 at $DIR/const_allocation.rs:8:5: 8:8 + // ty::Const + // + ty: &&[(std::option::Option, &[&str])] + // + val: Value(Scalar(alloc0+0)) + // mir::Constant + // + span: $DIR/const_allocation.rs:8:5: 8:8 + // + literal: Const { ty: &&[(std::option::Option, &[&str])], val: Value(Scalar(alloc0+0)) } + _1 = (*_2); // bb0[3]: scope 0 at $DIR/const_allocation.rs:8:5: 8:8 + StorageDead(_2); // bb0[4]: scope 0 at $DIR/const_allocation.rs:8:8: 8:9 + StorageDead(_1); // bb0[5]: scope 0 at $DIR/const_allocation.rs:8:8: 8:9 + _0 = (); // bb0[6]: scope 0 at $DIR/const_allocation.rs:7:11: 9:2 + return; // bb0[7]: scope 0 at $DIR/const_allocation.rs:9:2: 9:2 + } +} + +alloc0 (static: FOO, size: 8, align: 4) { + ╾alloc17+0╼ 03 00 00 00 │ ╾──╼.... +} + +alloc17 (size: 48, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾alloc4+0─╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾alloc8+0─╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾alloc13+0╼ 03 00 00 00 │ ....*...╾──╼.... +} + +alloc4 (size: 0, align: 4) {} + +alloc8 (size: 16, align: 4) { + ╾alloc7+0─╼ 03 00 00 00 ╾alloc9+0─╼ 03 00 00 00 │ ╾──╼....╾──╼.... +} + +alloc7 (size: 3, align: 1) { + 66 6f 6f │ foo +} + +alloc9 (size: 3, align: 1) { + 62 61 72 │ bar +} + +alloc13 (size: 24, align: 4) { + 0x00 │ ╾alloc12+0╼ 03 00 00 00 ╾alloc14+0╼ 03 00 00 00 │ ╾──╼....╾──╼.... + 0x10 │ ╾alloc15+0╼ 04 00 00 00 │ ╾──╼.... +} + +alloc12 (size: 3, align: 1) { + 6d 65 68 │ meh +} + +alloc14 (size: 3, align: 1) { + 6d 6f 70 │ mop +} + +alloc15 (size: 4, align: 1) { + 6d c3 b6 70 │ m..p +} diff --git a/src/test/mir-opt/const_allocation/64bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation/64bit/rustc.main.ConstProp.after.mir new file mode 100644 index 0000000000000..b60d23aa3f117 --- /dev/null +++ b/src/test/mir-opt/const_allocation/64bit/rustc.main.ConstProp.after.mir @@ -0,0 +1,69 @@ +// MIR for `main` after ConstProp + +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/const_allocation.rs:7:11: 7:11 + let _1: &[(std::option::Option, &[&str])]; // in scope 0 at $DIR/const_allocation.rs:8:5: 8:8 + let mut _2: &&[(std::option::Option, &[&str])]; // in scope 0 at $DIR/const_allocation.rs:8:5: 8:8 + + bb0: { + StorageLive(_1); // bb0[0]: scope 0 at $DIR/const_allocation.rs:8:5: 8:8 + StorageLive(_2); // bb0[1]: scope 0 at $DIR/const_allocation.rs:8:5: 8:8 + _2 = const {alloc0+0: &&[(std::option::Option, &[&str])]}; // bb0[2]: scope 0 at $DIR/const_allocation.rs:8:5: 8:8 + // ty::Const + // + ty: &&[(std::option::Option, &[&str])] + // + val: Value(Scalar(alloc0+0)) + // mir::Constant + // + span: $DIR/const_allocation.rs:8:5: 8:8 + // + literal: Const { ty: &&[(std::option::Option, &[&str])], val: Value(Scalar(alloc0+0)) } + _1 = (*_2); // bb0[3]: scope 0 at $DIR/const_allocation.rs:8:5: 8:8 + StorageDead(_2); // bb0[4]: scope 0 at $DIR/const_allocation.rs:8:8: 8:9 + StorageDead(_1); // bb0[5]: scope 0 at $DIR/const_allocation.rs:8:8: 8:9 + _0 = (); // bb0[6]: scope 0 at $DIR/const_allocation.rs:7:11: 9:2 + return; // bb0[7]: scope 0 at $DIR/const_allocation.rs:9:2: 9:2 + } +} + +alloc0 (static: FOO, size: 16, align: 8) { + ╾──────alloc17+0──────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +} + +alloc17 (size: 72, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾──────alloc4+0───────╼ │ ....░░░░╾──────╼ + 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ + 0x20 │ ╾──────alloc8+0───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾──────alloc13+0──────╼ │ ....*...╾──────╼ + 0x40 │ 03 00 00 00 00 00 00 00 │ ........ +} + +alloc4 (size: 0, align: 8) {} + +alloc8 (size: 32, align: 8) { + 0x00 │ ╾──────alloc7+0───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾──────alloc9+0───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +} + +alloc7 (size: 3, align: 1) { + 66 6f 6f │ foo +} + +alloc9 (size: 3, align: 1) { + 62 61 72 │ bar +} + +alloc13 (size: 48, align: 8) { + 0x00 │ ╾──────alloc12+0──────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾──────alloc14+0──────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x20 │ ╾──────alloc15+0──────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ +} + +alloc12 (size: 3, align: 1) { + 6d 65 68 │ meh +} + +alloc14 (size: 3, align: 1) { + 6d 6f 70 │ mop +} + +alloc15 (size: 4, align: 1) { + 6d c3 b6 70 │ m..p +} diff --git a/src/test/mir-opt/const_allocation2.rs b/src/test/mir-opt/const_allocation2.rs new file mode 100644 index 0000000000000..ca61b84c0bcad --- /dev/null +++ b/src/test/mir-opt/const_allocation2.rs @@ -0,0 +1,11 @@ +// EMIT_MIR_FOR_EACH_BIT_WIDTH + +// EMIT_MIR rustc.main.ConstProp.after.mir +fn main() { + FOO; +} + +const BAR: [u8; 4] = [42, 69, 21, 111]; + +static FOO: &[(Option, &[&u8])] = + &[(None, &[]), (None, &[&5, &6]), (Some(42), &[&BAR[3], &42, &BAR[2]])]; diff --git a/src/test/mir-opt/const_allocation2/32bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation2/32bit/rustc.main.ConstProp.after.mir new file mode 100644 index 0000000000000..6caecf1eceac0 --- /dev/null +++ b/src/test/mir-opt/const_allocation2/32bit/rustc.main.ConstProp.after.mir @@ -0,0 +1,64 @@ +// MIR for `main` after ConstProp + +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/const_allocation2.rs:4:11: 4:11 + let _1: &[(std::option::Option, &[&u8])]; // in scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 + let mut _2: &&[(std::option::Option, &[&u8])]; // in scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 + + bb0: { + StorageLive(_1); // bb0[0]: scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 + StorageLive(_2); // bb0[1]: scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 + _2 = const {alloc0+0: &&[(std::option::Option, &[&u8])]}; // bb0[2]: scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 + // ty::Const + // + ty: &&[(std::option::Option, &[&u8])] + // + val: Value(Scalar(alloc0+0)) + // mir::Constant + // + span: $DIR/const_allocation2.rs:5:5: 5:8 + // + literal: Const { ty: &&[(std::option::Option, &[&u8])], val: Value(Scalar(alloc0+0)) } + _1 = (*_2); // bb0[3]: scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 + StorageDead(_2); // bb0[4]: scope 0 at $DIR/const_allocation2.rs:5:8: 5:9 + StorageDead(_1); // bb0[5]: scope 0 at $DIR/const_allocation2.rs:5:8: 5:9 + _0 = (); // bb0[6]: scope 0 at $DIR/const_allocation2.rs:4:11: 6:2 + return; // bb0[7]: scope 0 at $DIR/const_allocation2.rs:6:2: 6:2 + } +} + +alloc0 (static: FOO, size: 8, align: 4) { + ╾alloc24+0╼ 03 00 00 00 │ ╾──╼.... +} + +alloc24 (size: 48, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾alloc9+0─╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾alloc14+0╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾alloc22+0╼ 03 00 00 00 │ ....*...╾──╼.... +} + +alloc9 (size: 0, align: 4) {} + +alloc14 (size: 8, align: 4) { + ╾alloc12+0╼ ╾alloc13+0╼ │ ╾──╼╾──╼ +} + +alloc12 (size: 1, align: 1) { + 05 │ . +} + +alloc13 (size: 1, align: 1) { + 06 │ . +} + +alloc22 (size: 12, align: 4) { + ╾alloc18+3╼ ╾alloc19+0╼ ╾alloc21+2╼ │ ╾──╼╾──╼╾──╼ +} + +alloc18 (size: 4, align: 1) { + 2a 45 15 6f │ *E.o +} + +alloc19 (size: 1, align: 1) { + 2a │ * +} + +alloc21 (size: 4, align: 1) { + 2a 45 15 6f │ *E.o +} diff --git a/src/test/mir-opt/const_allocation2/64bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation2/64bit/rustc.main.ConstProp.after.mir new file mode 100644 index 0000000000000..52e7c2aec2b12 --- /dev/null +++ b/src/test/mir-opt/const_allocation2/64bit/rustc.main.ConstProp.after.mir @@ -0,0 +1,67 @@ +// MIR for `main` after ConstProp + +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/const_allocation2.rs:4:11: 4:11 + let _1: &[(std::option::Option, &[&u8])]; // in scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 + let mut _2: &&[(std::option::Option, &[&u8])]; // in scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 + + bb0: { + StorageLive(_1); // bb0[0]: scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 + StorageLive(_2); // bb0[1]: scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 + _2 = const {alloc0+0: &&[(std::option::Option, &[&u8])]}; // bb0[2]: scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 + // ty::Const + // + ty: &&[(std::option::Option, &[&u8])] + // + val: Value(Scalar(alloc0+0)) + // mir::Constant + // + span: $DIR/const_allocation2.rs:5:5: 5:8 + // + literal: Const { ty: &&[(std::option::Option, &[&u8])], val: Value(Scalar(alloc0+0)) } + _1 = (*_2); // bb0[3]: scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 + StorageDead(_2); // bb0[4]: scope 0 at $DIR/const_allocation2.rs:5:8: 5:9 + StorageDead(_1); // bb0[5]: scope 0 at $DIR/const_allocation2.rs:5:8: 5:9 + _0 = (); // bb0[6]: scope 0 at $DIR/const_allocation2.rs:4:11: 6:2 + return; // bb0[7]: scope 0 at $DIR/const_allocation2.rs:6:2: 6:2 + } +} + +alloc0 (static: FOO, size: 16, align: 8) { + ╾──────alloc24+0──────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +} + +alloc24 (size: 72, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾──────alloc9+0───────╼ │ ....░░░░╾──────╼ + 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ + 0x20 │ ╾──────alloc14+0──────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾──────alloc22+0──────╼ │ ....*...╾──────╼ + 0x40 │ 03 00 00 00 00 00 00 00 │ ........ +} + +alloc9 (size: 0, align: 8) {} + +alloc14 (size: 16, align: 8) { + ╾──────alloc12+0──────╼ ╾──────alloc13+0──────╼ │ ╾──────╼╾──────╼ +} + +alloc12 (size: 1, align: 1) { + 05 │ . +} + +alloc13 (size: 1, align: 1) { + 06 │ . +} + +alloc22 (size: 24, align: 8) { + 0x00 │ ╾──────alloc18+3──────╼ ╾──────alloc19+0──────╼ │ ╾──────╼╾──────╼ + 0x10 │ ╾──────alloc21+2──────╼ │ ╾──────╼ +} + +alloc18 (size: 4, align: 1) { + 2a 45 15 6f │ *E.o +} + +alloc19 (size: 1, align: 1) { + 2a │ * +} + +alloc21 (size: 4, align: 1) { + 2a 45 15 6f │ *E.o +} diff --git a/src/test/mir-opt/const_allocation3.rs b/src/test/mir-opt/const_allocation3.rs new file mode 100644 index 0000000000000..73bb58e1a9892 --- /dev/null +++ b/src/test/mir-opt/const_allocation3.rs @@ -0,0 +1,29 @@ +// EMIT_MIR_FOR_EACH_BIT_WIDTH + +// EMIT_MIR rustc.main.ConstProp.after.mir +fn main() { + FOO; +} + +#[repr(packed)] +struct Packed { + a: [u8; 28], + b: &'static i32, + c: u32, + d: [u8; 102], + e: fn(), + f: u16, + g: &'static u8, + h: [u8; 20], +} + +static FOO: &Packed = &Packed { + a: [0xAB; 28], + b: &42, + c: 0xABCD_EF01, + d: [0; 102], + e: main, + f: 0, + g: &[0; 100][99], + h: [0; 20], +}; diff --git a/src/test/mir-opt/const_allocation3/32bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation3/32bit/rustc.main.ConstProp.after.mir new file mode 100644 index 0000000000000..4fc2c4c3fb3dd --- /dev/null +++ b/src/test/mir-opt/const_allocation3/32bit/rustc.main.ConstProp.after.mir @@ -0,0 +1,58 @@ +// MIR for `main` after ConstProp + +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/const_allocation3.rs:4:11: 4:11 + let _1: &Packed; // in scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 + let mut _2: &&Packed; // in scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 + + bb0: { + StorageLive(_1); // bb0[0]: scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 + StorageLive(_2); // bb0[1]: scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 + _2 = const {alloc0+0: &&Packed}; // bb0[2]: scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 + // ty::Const + // + ty: &&Packed + // + val: Value(Scalar(alloc0+0)) + // mir::Constant + // + span: $DIR/const_allocation3.rs:5:5: 5:8 + // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc0+0)) } + _1 = (*_2); // bb0[3]: scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 + StorageDead(_2); // bb0[4]: scope 0 at $DIR/const_allocation3.rs:5:8: 5:9 + StorageDead(_1); // bb0[5]: scope 0 at $DIR/const_allocation3.rs:5:8: 5:9 + _0 = (); // bb0[6]: scope 0 at $DIR/const_allocation3.rs:4:11: 6:2 + return; // bb0[7]: scope 0 at $DIR/const_allocation3.rs:6:2: 6:2 + } +} + +alloc0 (static: FOO, size: 4, align: 4) { + ╾alloc10+0╼ │ ╾──╼ +} + +alloc10 (size: 168, align: 1) { + 0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................ + 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾alloc5+0─╼ │ ............╾──╼ + 0x20 │ 01 ef cd ab 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x50 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾alloc7+0─╼ 00 00 │ ..........╾──╼.. + 0x90 │ ╾alloc8+99╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............ + 0xa0 │ 00 00 00 00 00 00 00 00 │ ........ +} + +alloc5 (size: 4, align: 4) { + 2a 00 00 00 │ *... +} + +alloc7 (fn: main) + +alloc8 (size: 100, align: 1) { + 0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x50 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x60 │ 00 00 00 00 │ .... +} diff --git a/src/test/mir-opt/const_allocation3/64bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation3/64bit/rustc.main.ConstProp.after.mir new file mode 100644 index 0000000000000..ae5ebe7043706 --- /dev/null +++ b/src/test/mir-opt/const_allocation3/64bit/rustc.main.ConstProp.after.mir @@ -0,0 +1,59 @@ +// MIR for `main` after ConstProp + +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/const_allocation3.rs:4:11: 4:11 + let _1: &Packed; // in scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 + let mut _2: &&Packed; // in scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 + + bb0: { + StorageLive(_1); // bb0[0]: scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 + StorageLive(_2); // bb0[1]: scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 + _2 = const {alloc0+0: &&Packed}; // bb0[2]: scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 + // ty::Const + // + ty: &&Packed + // + val: Value(Scalar(alloc0+0)) + // mir::Constant + // + span: $DIR/const_allocation3.rs:5:5: 5:8 + // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc0+0)) } + _1 = (*_2); // bb0[3]: scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 + StorageDead(_2); // bb0[4]: scope 0 at $DIR/const_allocation3.rs:5:8: 5:9 + StorageDead(_1); // bb0[5]: scope 0 at $DIR/const_allocation3.rs:5:8: 5:9 + _0 = (); // bb0[6]: scope 0 at $DIR/const_allocation3.rs:4:11: 6:2 + return; // bb0[7]: scope 0 at $DIR/const_allocation3.rs:6:2: 6:2 + } +} + +alloc0 (static: FOO, size: 8, align: 8) { + ╾──────alloc10+0──────╼ │ ╾──────╼ +} + +alloc10 (size: 180, align: 1) { + 0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................ + 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc5+0─ │ ............╾─── + 0x20 │ ──────────╼ 01 ef cd ab 00 00 00 00 00 00 00 00 │ ───╼............ + 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x50 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x80 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ╾──── │ ..............╾─ + 0x90 │ ────alloc7+0────╼ 00 00 ╾──────alloc8+99──────╼ │ ─────╼..╾──────╼ + 0xa0 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0xb0 │ 00 00 00 00 │ .... +} + +alloc5 (size: 4, align: 4) { + 2a 00 00 00 │ *... +} + +alloc7 (fn: main) + +alloc8 (size: 100, align: 1) { + 0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x50 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + 0x60 │ 00 00 00 00 │ .... +} diff --git a/src/test/mir-opt/const_prop/cast.rs b/src/test/mir-opt/const_prop/cast.rs index 9cfbfebdcc3df..2af5f32a66832 100644 --- a/src/test/mir-opt/const_prop/cast.rs +++ b/src/test/mir-opt/const_prop/cast.rs @@ -1,49 +1,7 @@ +// EMIT_MIR rustc.main.ConstProp.diff + fn main() { let x = 42u8 as u32; let y = 42u32 as u8; } - -// END RUST SOURCE -// START rustc.main.ConstProp.before.mir -// let mut _0: (); -// let _1: u32; -// scope 1 { -// debug x => _1; -// let _2: u8; -// scope 2 { -// debug y => _2; -// } -// } -// bb0: { -// StorageLive(_1); -// _1 = const 42u8 as u32 (Misc); -// StorageLive(_2); -// _2 = const 42u32 as u8 (Misc); -// _0 = (); -// StorageDead(_2); -// StorageDead(_1); -// return; -// } -// END rustc.main.ConstProp.before.mir -// START rustc.main.ConstProp.after.mir -// let mut _0: (); -// let _1: u32; -// scope 1 { -// debug x => _1; -// let _2: u8; -// scope 2 { -// debug y => _2; -// } -// } -// bb0: { -// StorageLive(_1); -// _1 = const 42u32; -// StorageLive(_2); -// _2 = const 42u8; -// _0 = (); -// StorageDead(_2); -// StorageDead(_1); -// return; -// } -// END rustc.main.ConstProp.after.mir diff --git a/src/test/mir-opt/const_prop/cast/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/cast/rustc.main.ConstProp.diff new file mode 100644 index 0000000000000..ee6a0e87b12fc --- /dev/null +++ b/src/test/mir-opt/const_prop/cast/rustc.main.ConstProp.diff @@ -0,0 +1,48 @@ +- // MIR for `main` before ConstProp ++ // MIR for `main` after ConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/cast.rs:3:11: 3:11 + let _1: u32; // in scope 0 at $DIR/cast.rs:4:9: 4:10 + scope 1 { + debug x => _1; // in scope 1 at $DIR/cast.rs:4:9: 4:10 + let _2: u8; // in scope 1 at $DIR/cast.rs:6:9: 6:10 + scope 2 { + debug y => _2; // in scope 2 at $DIR/cast.rs:6:9: 6:10 + } + } + + bb0: { + StorageLive(_1); // bb0[0]: scope 0 at $DIR/cast.rs:4:9: 4:10 +- _1 = const 42u8 as u32 (Misc); // bb0[1]: scope 0 at $DIR/cast.rs:4:13: 4:24 ++ _1 = const 42u32; // bb0[1]: scope 0 at $DIR/cast.rs:4:13: 4:24 + // ty::Const +- // + ty: u8 +- // + val: Value(Scalar(0x2a)) +- // mir::Constant +- // + span: $DIR/cast.rs:4:13: 4:17 +- // + literal: Const { ty: u8, val: Value(Scalar(0x2a)) } +- StorageLive(_2); // bb0[2]: scope 1 at $DIR/cast.rs:6:9: 6:10 +- _2 = const 42u32 as u8 (Misc); // bb0[3]: scope 1 at $DIR/cast.rs:6:13: 6:24 +- // ty::Const + // + ty: u32 + // + val: Value(Scalar(0x0000002a)) + // mir::Constant +- // + span: $DIR/cast.rs:6:13: 6:18 ++ // + span: $DIR/cast.rs:4:13: 4:24 + // + literal: Const { ty: u32, val: Value(Scalar(0x0000002a)) } ++ StorageLive(_2); // bb0[2]: scope 1 at $DIR/cast.rs:6:9: 6:10 ++ _2 = const 42u8; // bb0[3]: scope 1 at $DIR/cast.rs:6:13: 6:24 ++ // ty::Const ++ // + ty: u8 ++ // + val: Value(Scalar(0x2a)) ++ // mir::Constant ++ // + span: $DIR/cast.rs:6:13: 6:24 ++ // + literal: Const { ty: u8, val: Value(Scalar(0x2a)) } + _0 = (); // bb0[4]: scope 0 at $DIR/cast.rs:3:11: 7:2 + StorageDead(_2); // bb0[5]: scope 1 at $DIR/cast.rs:7:1: 7:2 + StorageDead(_1); // bb0[6]: scope 0 at $DIR/cast.rs:7:1: 7:2 + return; // bb0[7]: scope 0 at $DIR/cast.rs:7:2: 7:2 + } + } + diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 4508f5b7f95f4..0ee016f33dd88 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -11,6 +11,7 @@ use crate::common::{UI_RUN_STDERR, UI_RUN_STDOUT}; use crate::errors::{self, Error, ErrorKind}; use crate::header::TestProps; use crate::json; +use crate::util::get_pointer_width; use crate::util::{logv, PathBufExt}; use diff; use regex::{Captures, Regex}; @@ -178,6 +179,33 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { + writeln!(dest, "-\t{}", e).unwrap(); + line_number += 1; + } + DiffLine::Context(c) => { + writeln!(dest, "{}\t{}", line_number, c).unwrap(); + line_number += 1; + } + DiffLine::Resulting(r) => { + writeln!(dest, "+\t{}", r).unwrap(); + } + } + } + writeln!(dest).unwrap(); + } +} + pub fn run(config: Config, testpaths: &TestPaths, revision: Option<&str>) { match &*config.target { "arm-linux-androideabi" @@ -3040,6 +3068,89 @@ impl<'test> TestCx<'test> { fn check_mir_dump(&self) { let test_file_contents = fs::read_to_string(&self.testpaths.file).unwrap(); + + let mut test_dir = self.testpaths.file.with_extension(""); + + if test_file_contents.lines().any(|l| l == "// EMIT_MIR_FOR_EACH_BIT_WIDTH") { + test_dir.push(get_pointer_width(&self.config.target)) + } + + if self.config.bless { + let _ = std::fs::remove_dir_all(&test_dir); + } + for l in test_file_contents.lines() { + if l.starts_with("// EMIT_MIR ") { + let test_name = l.trim_start_matches("// EMIT_MIR "); + let expected_file = test_dir.join(test_name); + + let dumped_string = if test_name.ends_with(".diff") { + let test_name = test_name.trim_end_matches(".diff"); + let before = format!("{}.before.mir", test_name); + let after = format!("{}.after.mir", test_name); + let before = self.get_mir_dump_dir().join(before); + let after = self.get_mir_dump_dir().join(after); + debug!( + "comparing the contents of: {} with {}", + before.display(), + after.display() + ); + let before = fs::read_to_string(before).unwrap(); + let after = fs::read_to_string(after).unwrap(); + let before = self.normalize_output(&before, &[]); + let after = self.normalize_output(&after, &[]); + let mut dumped_string = String::new(); + for result in diff::lines(&before, &after) { + use std::fmt::Write; + match result { + diff::Result::Left(s) => writeln!(dumped_string, "- {}", s).unwrap(), + diff::Result::Right(s) => writeln!(dumped_string, "+ {}", s).unwrap(), + diff::Result::Both(s, _) => writeln!(dumped_string, " {}", s).unwrap(), + } + } + dumped_string + } else { + let mut output_file = PathBuf::new(); + output_file.push(self.get_mir_dump_dir()); + output_file.push(test_name); + debug!( + "comparing the contents of: {} with {}", + output_file.display(), + expected_file.display() + ); + if !output_file.exists() { + panic!( + "Output file `{}` from test does not exist, available files are in `{}`", + output_file.display(), + output_file.parent().unwrap().display() + ); + } + self.check_mir_test_timestamp(test_name, &output_file); + let dumped_string = fs::read_to_string(&output_file).unwrap(); + self.normalize_output(&dumped_string, &[]) + }; + if self.config.bless { + let _ = std::fs::create_dir_all(&test_dir); + let _ = std::fs::remove_file(&expected_file); + std::fs::write(expected_file, dumped_string.as_bytes()).unwrap(); + } else { + if !expected_file.exists() { + panic!( + "Output file `{}` from test does not exist", + expected_file.display() + ); + } + let expected_string = fs::read_to_string(&expected_file).unwrap(); + if dumped_string != expected_string { + print_diff(&dumped_string, &expected_string, 3); + panic!( + "Actual MIR output differs from expected MIR output {}", + expected_file.display() + ); + } + } + } + } + if let Some(idx) = test_file_contents.find("// END RUST SOURCE") { let (_, tests_text) = test_file_contents.split_at(idx + "// END_RUST SOURCE".len()); let tests_text_str = String::from(tests_text); @@ -3090,13 +3201,10 @@ impl<'test> TestCx<'test> { let mut output_file = PathBuf::new(); output_file.push(self.get_mir_dump_dir()); output_file.push(test_name); - debug!("comparing the contests of: {:?}", output_file); + debug!("comparing the contents of: {:?}", output_file); debug!("with: {:?}", expected_content); if !output_file.exists() { - panic!( - "Output file `{}` from test does not exist", - output_file.into_os_string().to_string_lossy() - ); + panic!("Output file `{}` from test does not exist", output_file.display()); } self.check_mir_test_timestamp(test_name, &output_file); @@ -3356,26 +3464,7 @@ impl<'test> TestCx<'test> { println!("normalized {}:\n{}\n", kind, actual); } else { println!("diff of {}:\n", kind); - let diff_results = make_diff(expected, actual, 3); - for result in diff_results { - let mut line_number = result.line_number; - for line in result.lines { - match line { - DiffLine::Expected(e) => { - println!("-\t{}", e); - line_number += 1; - } - DiffLine::Context(c) => { - println!("{}\t{}", line_number, c); - line_number += 1; - } - DiffLine::Resulting(r) => { - println!("+\t{}", r); - } - } - } - println!(); - } + print_diff(expected, actual, 3); } }