mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-30 16:43:41 +00:00
Enable --bless
ing of MIR dumps
This commit is contained in:
parent
fdc931899d
commit
c9a5a03ffd
@ -110,13 +110,13 @@ impl<K: Ord, V> SortedMap<K, V> {
|
||||
|
||||
/// Iterate over the keys, sorted
|
||||
#[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)
|
||||
}
|
||||
|
||||
/// Iterate over values, sorted by key
|
||||
#[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)
|
||||
}
|
||||
|
||||
|
@ -649,58 +649,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
|
||||
&self,
|
||||
allocs_seen: &mut FxHashSet<AllocId>,
|
||||
allocs_to_print: &mut VecDeque<AllocId>,
|
||||
mut msg: String,
|
||||
alloc: &Allocation<Tag, Extra>,
|
||||
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<Tag, Extra>(alloc: &Allocation<Tag, Extra>, 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)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<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(
|
||||
tcx: TyCtxt<'_>,
|
||||
src: MirSource<'tcx>,
|
||||
|
@ -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)
|
||||
|
@ -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<Box<u32>> = None;
|
||||
let drop_x: Option<Box<u32>> = 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::<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
|
||||
|
@ -0,0 +1,90 @@
|
||||
// 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 @@ 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::<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
|
||||
|
@ -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 │ *...
|
||||
}
|
@ -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::<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 │ *...
|
||||
}
|
||||
|
@ -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)
|
@ -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::<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)
|
||||
|
9
src/test/mir-opt/const_allocation.rs
Normal file
9
src/test/mir-opt/const_allocation.rs
Normal file
@ -0,0 +1,9 @@
|
||||
// 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;
|
||||
}
|
@ -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<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
|
||||
}
|
@ -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<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
|
||||
}
|
11
src/test/mir-opt/const_allocation2.rs
Normal file
11
src/test/mir-opt/const_allocation2.rs
Normal file
@ -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<i32>, &[&u8])] =
|
||||
&[(None, &[]), (None, &[&5, &6]), (Some(42), &[&BAR[3], &42, &BAR[2]])];
|
@ -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<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
|
||||
}
|
@ -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<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
|
||||
}
|
29
src/test/mir-opt/const_allocation3.rs
Normal file
29
src/test/mir-opt/const_allocation3.rs
Normal file
@ -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],
|
||||
};
|
@ -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 │ ....
|
||||
}
|
@ -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 │ ....
|
||||
}
|
@ -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
|
||||
|
48
src/test/mir-opt/const_prop/cast/rustc.main.ConstProp.diff
Normal file
48
src/test/mir-opt/const_prop/cast/rustc.main.ConstProp.diff
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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<Misma
|
||||
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>) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user