提交 0a2df620 编写于 作者: B bors

Auto merge of #69916 - oli-obk:mir_bless, r=eddyb

Enable blessing of mir opt tests

cc @rust-lang/wg-mir-opt
cc @RalfJung

Long overdue, but now you can finally just add a

```rust
// EMIT_MIR rustc.function_name.MirPassName.before.mir
```

(or `after.mir` since most of the time you want to know the MIR after a pass). A `--bless` invocation will automatically create the files for you.

I suggest we do this for all mir opt tests that have all of the MIR in their source anyway

If you use `rustc.function.MirPass.diff` you only get the diff that the MIR pass causes on the MIR.

Fixes #67865
...@@ -110,13 +110,13 @@ pub fn iter(&self) -> ::std::slice::Iter<'_, (K, V)> { ...@@ -110,13 +110,13 @@ pub fn iter(&self) -> ::std::slice::Iter<'_, (K, V)> {
/// Iterate over the keys, sorted /// Iterate over the keys, sorted
#[inline] #[inline]
pub fn keys(&self) -> impl Iterator<Item = &K> + ExactSizeIterator { pub fn keys(&self) -> impl Iterator<Item = &K> + ExactSizeIterator + DoubleEndedIterator {
self.data.iter().map(|&(ref k, _)| k) self.data.iter().map(|&(ref k, _)| k)
} }
/// Iterate over values, sorted by key /// Iterate over values, sorted by key
#[inline] #[inline]
pub fn values(&self) -> impl Iterator<Item = &V> + ExactSizeIterator { pub fn values(&self) -> impl Iterator<Item = &V> + ExactSizeIterator + DoubleEndedIterator {
self.data.iter().map(|&(_, ref v)| v) self.data.iter().map(|&(_, ref v)| v)
} }
......
...@@ -649,58 +649,15 @@ fn dump_alloc_helper<Tag, Extra>( ...@@ -649,58 +649,15 @@ fn dump_alloc_helper<Tag, Extra>(
&self, &self,
allocs_seen: &mut FxHashSet<AllocId>, allocs_seen: &mut FxHashSet<AllocId>,
allocs_to_print: &mut VecDeque<AllocId>, allocs_to_print: &mut VecDeque<AllocId>,
mut msg: String,
alloc: &Allocation<Tag, Extra>, alloc: &Allocation<Tag, Extra>,
extra: String,
) { ) {
use std::fmt::Write; for &(_, (_, target_id)) in alloc.relocations().iter() {
if allocs_seen.insert(target_id) {
let prefix_len = msg.len(); allocs_to_print.push_back(target_id);
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("__ ");
} }
} }
crate::util::pretty::write_allocation(self.tcx.tcx, alloc, &mut std::io::stderr(), "")
eprintln!( .unwrap();
"{}({} 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);
}
} }
/// Print a list of allocations and all allocations they point to, recursively. /// Print a list of allocations and all allocations they point to, recursively.
...@@ -713,45 +670,42 @@ pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) { ...@@ -713,45 +670,42 @@ pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
let mut allocs_seen = FxHashSet::default(); let mut allocs_seen = FxHashSet::default();
while let Some(id) = allocs_to_print.pop_front() { while let Some(id) = allocs_to_print.pop_front() {
let msg = format!("Alloc {:<5} ", format!("{}:", id)); eprint!("Alloc {:<5}: ", id);
fn msg<Tag, Extra>(alloc: &Allocation<Tag, Extra>, extra: &str) {
eprintln!(
"({} bytes, alignment {}){}",
alloc.size.bytes(),
alloc.align.bytes(),
extra
)
};
// normal alloc? // normal alloc?
match self.alloc_map.get_or(id, || Err(())) { match self.alloc_map.get_or(id, || Err(())) {
Ok((kind, alloc)) => { Ok((kind, alloc)) => {
let extra = match kind { match kind {
MemoryKind::Stack => " (stack)".to_owned(), MemoryKind::Stack => msg(alloc, " (stack)"),
MemoryKind::Vtable => " (vtable)".to_owned(), MemoryKind::Vtable => msg(alloc, " (vtable)"),
MemoryKind::CallerLocation => " (caller_location)".to_owned(), MemoryKind::CallerLocation => msg(alloc, " (caller_location)"),
MemoryKind::Machine(m) => format!(" ({:?})", m), MemoryKind::Machine(m) => msg(alloc, &format!(" ({:?})", m)),
}; };
self.dump_alloc_helper( self.dump_alloc_helper(&mut allocs_seen, &mut allocs_to_print, alloc);
&mut allocs_seen,
&mut allocs_to_print,
msg,
alloc,
extra,
);
} }
Err(()) => { Err(()) => {
// global alloc? // global alloc?
match self.tcx.alloc_map.lock().get(id) { match self.tcx.alloc_map.lock().get(id) {
Some(GlobalAlloc::Memory(alloc)) => { Some(GlobalAlloc::Memory(alloc)) => {
self.dump_alloc_helper( msg(alloc, " (immutable)");
&mut allocs_seen, self.dump_alloc_helper(&mut allocs_seen, &mut allocs_to_print, alloc);
&mut allocs_to_print,
msg,
alloc,
" (immutable)".to_owned(),
);
} }
Some(GlobalAlloc::Function(func)) => { Some(GlobalAlloc::Function(func)) => {
eprintln!("{} {}", msg, func); eprintln!("{}", func);
} }
Some(GlobalAlloc::Static(did)) => { Some(GlobalAlloc::Static(did)) => {
eprintln!("{} {:?}", msg, did); eprintln!("{:?}", did);
} }
None => { None => {
eprintln!("{} (deallocated)", msg); eprintln!("(deallocated)");
} }
} }
} }
......
use super::graphviz::write_mir_fn_graphviz; use super::graphviz::write_mir_fn_graphviz;
use crate::transform::MirSource; 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::visit::Visitor;
use rustc::mir::*; 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_data_structures::fx::FxHashMap;
use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_index::vec::Idx; use rustc_index::vec::Idx;
use std::collections::BTreeSet;
use std::fmt::Display; use std::fmt::Display;
use std::fmt::Write as _; use std::fmt::Write as _;
use std::fs; use std::fs;
...@@ -77,20 +80,7 @@ pub fn dump_mir<'tcx, F>( ...@@ -77,20 +80,7 @@ pub fn dump_mir<'tcx, F>(
return; return;
} }
let node_path = ty::print::with_forced_impl_filename_line(|| { dump_matched_mir_node(tcx, pass_num, pass_name, disambiguator, source, body, extra_data);
// 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,
);
} }
pub fn dump_enabled<'tcx>(tcx: TyCtxt<'tcx>, pass_name: &str, source: MirSource<'tcx>) -> bool { 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>( ...@@ -117,7 +107,6 @@ fn dump_matched_mir_node<'tcx, F>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
pass_num: Option<&dyn Display>, pass_num: Option<&dyn Display>,
pass_name: &str, pass_name: &str,
node_path: &str,
disambiguator: &dyn Display, disambiguator: &dyn Display,
source: MirSource<'tcx>, source: MirSource<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
...@@ -127,10 +116,16 @@ fn dump_matched_mir_node<'tcx, F>( ...@@ -127,10 +116,16 @@ fn dump_matched_mir_node<'tcx, F>(
{ {
let _: io::Result<()> = try { let _: io::Result<()> = try {
let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, source)?; let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, source)?;
writeln!(file, "// MIR for `{}`", node_path)?; let def_path = ty::print::with_forced_impl_filename_line(|| {
writeln!(file, "// source = {:?}", source)?; // see notes on #41697 above
writeln!(file, "// pass_name = {}", pass_name)?; tcx.def_path_str(source.def_id())
writeln!(file, "// disambiguator = {}", disambiguator)?; });
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 { if let Some(ref layout) = body.generator_layout {
writeln!(file, "// generator_layout = {:?}", layout)?; writeln!(file, "// generator_layout = {:?}", layout)?;
} }
...@@ -276,6 +271,9 @@ pub fn write_mir_fn<'tcx, F>( ...@@ -276,6 +271,9 @@ pub fn write_mir_fn<'tcx, F>(
} }
writeln!(w, "}}")?; writeln!(w, "}}")?;
write_allocations(tcx, body, w)?;
Ok(()) Ok(())
} }
...@@ -534,6 +532,250 @@ pub fn write_mir_intro<'tcx>( ...@@ -534,6 +532,250 @@ pub fn write_mir_intro<'tcx>(
Ok(()) 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<Item = AllocId> + '_ {
alloc.relocations().values().map(|(_, id)| *id)
}
fn alloc_ids_from_const(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ {
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<AllocId>);
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<Size> {
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<Tag, Extra>(
tcx: TyCtxt<'tcx>,
alloc: &Allocation<Tag, Extra>,
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( fn write_mir_sig(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
src: MirSource<'tcx>, src: MirSource<'tcx>,
......
This folder contains tests for MIR optimizations. 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) (arbitrary rust code)
......
// this tests move up progration, which is not yet implemented // 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 // Check codegen for assignments (`a = b`) where the left-hand-side is
// not yet initialized. Assignments tend to be absent in simple code, // 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 // so subtle breakage in them can leave a quite hard-to-find trail of
...@@ -13,40 +15,10 @@ fn main() { ...@@ -13,40 +15,10 @@ fn main() {
// assignment: // assignment:
nodrop_y = nodrop_x; nodrop_y = nodrop_x;
let drop_x : Option<Box<u32>> = None; let drop_x: Option<Box<u32>> = None;
let drop_y; let drop_y;
// Since the type of `drop_y` has drop, we generate a `replace` // Since the type of `drop_y` has drop, we generate a `replace`
// terminator: // terminator:
drop_y = drop_x; 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::<std::boxed::Box<u32>>::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
// MIR for `main` after SimplifyCfg-initial
| User Type Annotations
| 0: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option<std::boxed::Box<u32>>) } at $DIR/basic_assignment.rs:18:17: 18:33
| 1: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option<std::boxed::Box<u32>>) } 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<std::boxed::Box<u32>>; // 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<std::boxed::Box<u32>> 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<std::boxed::Box<u32>>; // 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::<std::boxed::Box<u32>>::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
}
}
...@@ -4,70 +4,12 @@ ...@@ -4,70 +4,12 @@
static Y: i32 = 42; 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(); 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(); static mut FOO: *const &i32 = [unsafe { &X }].as_ptr();
fn main() {} 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::<impl [&i32]>::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::<impl [&i32]>::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::<impl [&i32]>::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::<impl [&i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
// }
// ...
// bb2: {
// return;
// }
// END rustc.FOO.PromoteTemps.after.mir
// 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 │ *...
}
- // 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::<impl [&i32]>::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::<impl [&i32]>::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::<impl [&i32]>::as_ptr}
// + val: Value(Scalar(<ZST>))
// 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::<impl [&i32]>::as_ptr}, val: Value(Scalar(<ZST>)) }
}
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 │ *...
}
// 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)
- // 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::<impl [&i32]>::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::<impl [&i32]>::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::<impl [&i32]>::as_ptr}
// + val: Value(Scalar(<ZST>))
// 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::<impl [&i32]>::as_ptr}, val: Value(Scalar(<ZST>)) }
}
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)
// EMIT_MIR_FOR_EACH_BIT_WIDTH
static FOO: &[(Option<i32>, &[&str])] =
&[(None, &[]), (None, &["foo", "bar"]), (Some(42), &["meh", "mop", "möp"])];
// EMIT_MIR rustc.main.ConstProp.after.mir
fn main() {
FOO;
}
// 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<i32>, &[&str])]; // in scope 0 at $DIR/const_allocation.rs:8:5: 8:8
let mut _2: &&[(std::option::Option<i32>, &[&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<i32>, &[&str])]}; // bb0[2]: scope 0 at $DIR/const_allocation.rs:8:5: 8:8
// ty::Const
// + ty: &&[(std::option::Option<i32>, &[&str])]
// + val: Value(Scalar(alloc0+0))
// mir::Constant
// + span: $DIR/const_allocation.rs:8:5: 8:8
// + literal: Const { ty: &&[(std::option::Option<i32>, &[&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
}
// 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<i32>, &[&str])]; // in scope 0 at $DIR/const_allocation.rs:8:5: 8:8
let mut _2: &&[(std::option::Option<i32>, &[&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<i32>, &[&str])]}; // bb0[2]: scope 0 at $DIR/const_allocation.rs:8:5: 8:8
// ty::Const
// + ty: &&[(std::option::Option<i32>, &[&str])]
// + val: Value(Scalar(alloc0+0))
// mir::Constant
// + span: $DIR/const_allocation.rs:8:5: 8:8
// + literal: Const { ty: &&[(std::option::Option<i32>, &[&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
}
// 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<i32>, &[&u8])] =
&[(None, &[]), (None, &[&5, &6]), (Some(42), &[&BAR[3], &42, &BAR[2]])];
// 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<i32>, &[&u8])]; // in scope 0 at $DIR/const_allocation2.rs:5:5: 5:8
let mut _2: &&[(std::option::Option<i32>, &[&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<i32>, &[&u8])]}; // bb0[2]: scope 0 at $DIR/const_allocation2.rs:5:5: 5:8
// ty::Const
// + ty: &&[(std::option::Option<i32>, &[&u8])]
// + val: Value(Scalar(alloc0+0))
// mir::Constant
// + span: $DIR/const_allocation2.rs:5:5: 5:8
// + literal: Const { ty: &&[(std::option::Option<i32>, &[&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
}
// 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<i32>, &[&u8])]; // in scope 0 at $DIR/const_allocation2.rs:5:5: 5:8
let mut _2: &&[(std::option::Option<i32>, &[&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<i32>, &[&u8])]}; // bb0[2]: scope 0 at $DIR/const_allocation2.rs:5:5: 5:8
// ty::Const
// + ty: &&[(std::option::Option<i32>, &[&u8])]
// + val: Value(Scalar(alloc0+0))
// mir::Constant
// + span: $DIR/const_allocation2.rs:5:5: 5:8
// + literal: Const { ty: &&[(std::option::Option<i32>, &[&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
}
// 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],
};
// 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 │ ....
}
// 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 │ ....
}
// EMIT_MIR rustc.main.ConstProp.diff
fn main() { fn main() {
let x = 42u8 as u32; let x = 42u8 as u32;
let y = 42u32 as u8; 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
- // 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
}
}
...@@ -449,15 +449,8 @@ pub fn test_opts(config: &Config) -> test::TestOpts { ...@@ -449,15 +449,8 @@ pub fn test_opts(config: &Config) -> test::TestOpts {
pub fn make_tests(config: &Config, tests: &mut Vec<test::TestDescAndFn>) { pub fn make_tests(config: &Config, tests: &mut Vec<test::TestDescAndFn>) {
debug!("making tests from {:?}", config.src_base.display()); debug!("making tests from {:?}", config.src_base.display());
let inputs = common_inputs_stamp(config); let inputs = common_inputs_stamp(config);
collect_tests_from_dir( collect_tests_from_dir(config, &config.src_base, &PathBuf::new(), &inputs, tests)
config, .expect(&format!("Could not read tests from {}", config.src_base.display()));
&config.src_base,
&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. /// Returns a stamp constructed from input files common to all test cases.
...@@ -494,7 +487,6 @@ fn common_inputs_stamp(config: &Config) -> Stamp { ...@@ -494,7 +487,6 @@ fn common_inputs_stamp(config: &Config) -> Stamp {
fn collect_tests_from_dir( fn collect_tests_from_dir(
config: &Config, config: &Config,
base: &Path,
dir: &Path, dir: &Path,
relative_dir_path: &Path, relative_dir_path: &Path,
inputs: &Stamp, inputs: &Stamp,
...@@ -538,14 +530,7 @@ fn collect_tests_from_dir( ...@@ -538,14 +530,7 @@ fn collect_tests_from_dir(
let relative_file_path = relative_dir_path.join(file.file_name()); let relative_file_path = relative_dir_path.join(file.file_name());
if &file_name != "auxiliary" { if &file_name != "auxiliary" {
debug!("found directory: {:?}", file_path.display()); debug!("found directory: {:?}", file_path.display());
collect_tests_from_dir( collect_tests_from_dir(config, &file_path, &relative_file_path, inputs, tests)?;
config,
base,
&file_path,
&relative_file_path,
inputs,
tests,
)?;
} }
} else { } else {
debug!("found other file/directory: {:?}", file_path.display()); debug!("found other file/directory: {:?}", file_path.display());
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
use crate::errors::{self, Error, ErrorKind}; use crate::errors::{self, Error, ErrorKind};
use crate::header::TestProps; use crate::header::TestProps;
use crate::json; use crate::json;
use crate::util::get_pointer_width;
use crate::util::{logv, PathBufExt}; use crate::util::{logv, PathBufExt};
use diff; use diff;
use regex::{Captures, Regex}; use regex::{Captures, Regex};
...@@ -178,6 +179,33 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Misma ...@@ -178,6 +179,33 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Misma
results results
} }
fn print_diff(expected: &str, actual: &str, context_size: usize) {
write_diff(expected, actual, context_size, std::io::stdout());
}
fn write_diff(expected: &str, actual: &str, context_size: usize, mut dest: impl io::Write) {
let diff_results = make_diff(expected, actual, context_size);
for result in diff_results {
let mut line_number = result.line_number;
for line in result.lines {
match line {
DiffLine::Expected(e) => {
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>) { pub fn run(config: Config, testpaths: &TestPaths, revision: Option<&str>) {
match &*config.target { match &*config.target {
"arm-linux-androideabi" "arm-linux-androideabi"
...@@ -3040,6 +3068,89 @@ fn run_mir_opt_test(&self) { ...@@ -3040,6 +3068,89 @@ fn run_mir_opt_test(&self) {
fn check_mir_dump(&self) { fn check_mir_dump(&self) {
let test_file_contents = fs::read_to_string(&self.testpaths.file).unwrap(); 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") { 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) = test_file_contents.split_at(idx + "// END_RUST SOURCE".len());
let tests_text_str = String::from(tests_text); let tests_text_str = String::from(tests_text);
...@@ -3090,13 +3201,10 @@ fn compare_mir_test_output(&self, test_name: &str, expected_content: &[ExpectedL ...@@ -3090,13 +3201,10 @@ fn compare_mir_test_output(&self, test_name: &str, expected_content: &[ExpectedL
let mut output_file = PathBuf::new(); let mut output_file = PathBuf::new();
output_file.push(self.get_mir_dump_dir()); output_file.push(self.get_mir_dump_dir());
output_file.push(test_name); output_file.push(test_name);
debug!("comparing the contests of: {:?}", output_file); debug!("comparing the contents of: {:?}", output_file);
debug!("with: {:?}", expected_content); debug!("with: {:?}", expected_content);
if !output_file.exists() { if !output_file.exists() {
panic!( panic!("Output file `{}` from test does not exist", output_file.display());
"Output file `{}` from test does not exist",
output_file.into_os_string().to_string_lossy()
);
} }
self.check_mir_test_timestamp(test_name, &output_file); self.check_mir_test_timestamp(test_name, &output_file);
...@@ -3356,26 +3464,7 @@ fn compare_output(&self, kind: &str, actual: &str, expected: &str) -> usize { ...@@ -3356,26 +3464,7 @@ fn compare_output(&self, kind: &str, actual: &str, expected: &str) -> usize {
println!("normalized {}:\n{}\n", kind, actual); println!("normalized {}:\n{}\n", kind, actual);
} else { } else {
println!("diff of {}:\n", kind); println!("diff of {}:\n", kind);
let diff_results = make_diff(expected, actual, 3); print_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!();
}
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册