Improve emit stable mir body
This commit is contained in:
parent
3c85e56249
commit
ff504a09fe
9 changed files with 350 additions and 562 deletions
|
@ -10,7 +10,7 @@ use rustc_span::Symbol;
|
||||||
use stable_mir::abi::Layout;
|
use stable_mir::abi::Layout;
|
||||||
use stable_mir::mir::alloc::AllocId;
|
use stable_mir::mir::alloc::AllocId;
|
||||||
use stable_mir::mir::mono::{Instance, MonoItem, StaticDef};
|
use stable_mir::mir::mono::{Instance, MonoItem, StaticDef};
|
||||||
use stable_mir::mir::{Mutability, Safety};
|
use stable_mir::mir::{Mutability, Place, ProjectionElem, Safety};
|
||||||
use stable_mir::ty::{
|
use stable_mir::ty::{
|
||||||
Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const,
|
Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const,
|
||||||
DynKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig,
|
DynKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig,
|
||||||
|
@ -492,6 +492,50 @@ impl RustcInternal for Layout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RustcInternal for Place {
|
||||||
|
type T<'tcx> = rustc_middle::mir::Place<'tcx>;
|
||||||
|
|
||||||
|
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||||
|
rustc_middle::mir::Place {
|
||||||
|
local: rustc_middle::mir::Local::from_usize(self.local),
|
||||||
|
projection: tcx.mk_place_elems(&self.projection.internal(tables, tcx)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RustcInternal for ProjectionElem {
|
||||||
|
type T<'tcx> = rustc_middle::mir::PlaceElem<'tcx>;
|
||||||
|
|
||||||
|
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||||
|
match self {
|
||||||
|
ProjectionElem::Deref => rustc_middle::mir::PlaceElem::Deref,
|
||||||
|
ProjectionElem::Field(idx, ty) => {
|
||||||
|
rustc_middle::mir::PlaceElem::Field((*idx).into(), ty.internal(tables, tcx))
|
||||||
|
}
|
||||||
|
ProjectionElem::Index(idx) => rustc_middle::mir::PlaceElem::Index((*idx).into()),
|
||||||
|
ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
|
||||||
|
rustc_middle::mir::PlaceElem::ConstantIndex {
|
||||||
|
offset: *offset,
|
||||||
|
min_length: *min_length,
|
||||||
|
from_end: *from_end,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ProjectionElem::Subslice { from, to, from_end } => {
|
||||||
|
rustc_middle::mir::PlaceElem::Subslice { from: *from, to: *to, from_end: *from_end }
|
||||||
|
}
|
||||||
|
ProjectionElem::Downcast(idx) => {
|
||||||
|
rustc_middle::mir::PlaceElem::Downcast(None, idx.internal(tables, tcx))
|
||||||
|
}
|
||||||
|
ProjectionElem::OpaqueCast(ty) => {
|
||||||
|
rustc_middle::mir::PlaceElem::OpaqueCast(ty.internal(tables, tcx))
|
||||||
|
}
|
||||||
|
ProjectionElem::Subtype(ty) => {
|
||||||
|
rustc_middle::mir::PlaceElem::Subtype(ty.internal(tables, tcx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> RustcInternal for &T
|
impl<T> RustcInternal for &T
|
||||||
where
|
where
|
||||||
T: RustcInternal,
|
T: RustcInternal,
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub fn write_smir_pretty<'tcx, W: io::Write>(tcx: TyCtxt<'tcx>, w: &mut W) -> io
|
||||||
)?;
|
)?;
|
||||||
let _ = run(tcx, || {
|
let _ = run(tcx, || {
|
||||||
let items = stable_mir::all_local_items();
|
let items = stable_mir::all_local_items();
|
||||||
let _ = items.iter().map(|item| -> io::Result<()> { item.dump(w) }).collect::<Vec<_>>();
|
let _ = items.iter().map(|item| -> io::Result<()> { item.emit_mir(w) }).collect::<Vec<_>>();
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ use stable_mir::abi::{FnAbi, Layout, LayoutShape};
|
||||||
use stable_mir::compiler_interface::Context;
|
use stable_mir::compiler_interface::Context;
|
||||||
use stable_mir::mir::alloc::GlobalAlloc;
|
use stable_mir::mir::alloc::GlobalAlloc;
|
||||||
use stable_mir::mir::mono::{InstanceDef, StaticDef};
|
use stable_mir::mir::mono::{InstanceDef, StaticDef};
|
||||||
use stable_mir::mir::Body;
|
use stable_mir::mir::{Body, Place};
|
||||||
use stable_mir::target::{MachineInfo, MachineSize};
|
use stable_mir::target::{MachineInfo, MachineSize};
|
||||||
use stable_mir::ty::{
|
use stable_mir::ty::{
|
||||||
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
|
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
|
||||||
|
@ -423,7 +423,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
||||||
def_ty.instantiate(tables.tcx, args).stable(&mut *tables)
|
def_ty.instantiate(tables.tcx, args).stable(&mut *tables)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn const_literal(&self, cnst: &stable_mir::ty::Const) -> String {
|
fn const_pretty(&self, cnst: &stable_mir::ty::Const) -> String {
|
||||||
let mut tables = self.0.borrow_mut();
|
let mut tables = self.0.borrow_mut();
|
||||||
let tcx = tables.tcx;
|
let tcx = tables.tcx;
|
||||||
cnst.internal(&mut *tables, tcx).to_string()
|
cnst.internal(&mut *tables, tcx).to_string()
|
||||||
|
@ -434,6 +434,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
||||||
tables.tcx.def_span(tables[def_id]).stable(&mut *tables)
|
tables.tcx.def_span(tables[def_id]).stable(&mut *tables)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ty_pretty(&self, ty: stable_mir::ty::Ty) -> String {
|
||||||
|
let tables = self.0.borrow_mut();
|
||||||
|
tables.types[ty].to_string()
|
||||||
|
}
|
||||||
|
|
||||||
fn ty_kind(&self, ty: stable_mir::ty::Ty) -> TyKind {
|
fn ty_kind(&self, ty: stable_mir::ty::Ty) -> TyKind {
|
||||||
let mut tables = self.0.borrow_mut();
|
let mut tables = self.0.borrow_mut();
|
||||||
tables.types[ty].kind().stable(&mut *tables)
|
tables.types[ty].kind().stable(&mut *tables)
|
||||||
|
@ -654,6 +659,12 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
||||||
let tcx = tables.tcx;
|
let tcx = tables.tcx;
|
||||||
id.internal(&mut *tables, tcx).0.stable(&mut *tables)
|
id.internal(&mut *tables, tcx).0.stable(&mut *tables)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn place_debug(&self, place: &Place) -> String {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let tcx = tables.tcx;
|
||||||
|
format!("{:?}", place.internal(&mut *tables, tcx))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TablesWrapper<'tcx>(pub RefCell<Tables<'tcx>>);
|
pub struct TablesWrapper<'tcx>(pub RefCell<Tables<'tcx>>);
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::cell::Cell;
|
||||||
use crate::abi::{FnAbi, Layout, LayoutShape};
|
use crate::abi::{FnAbi, Layout, LayoutShape};
|
||||||
use crate::mir::alloc::{AllocId, GlobalAlloc};
|
use crate::mir::alloc::{AllocId, GlobalAlloc};
|
||||||
use crate::mir::mono::{Instance, InstanceDef, StaticDef};
|
use crate::mir::mono::{Instance, InstanceDef, StaticDef};
|
||||||
use crate::mir::Body;
|
use crate::mir::{Body, Place};
|
||||||
use crate::target::MachineInfo;
|
use crate::target::MachineInfo;
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
|
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
|
||||||
|
@ -126,11 +126,14 @@ pub trait Context {
|
||||||
fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty;
|
fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty;
|
||||||
|
|
||||||
/// Returns literal value of a const as a string.
|
/// Returns literal value of a const as a string.
|
||||||
fn const_literal(&self, cnst: &Const) -> String;
|
fn const_pretty(&self, cnst: &Const) -> String;
|
||||||
|
|
||||||
/// `Span` of an item
|
/// `Span` of an item
|
||||||
fn span_of_an_item(&self, def_id: DefId) -> Span;
|
fn span_of_an_item(&self, def_id: DefId) -> Span;
|
||||||
|
|
||||||
|
/// Obtain the representation of a type.
|
||||||
|
fn ty_pretty(&self, ty: Ty) -> String;
|
||||||
|
|
||||||
/// Obtain the representation of a type.
|
/// Obtain the representation of a type.
|
||||||
fn ty_kind(&self, ty: Ty) -> TyKind;
|
fn ty_kind(&self, ty: Ty) -> TyKind;
|
||||||
|
|
||||||
|
@ -205,6 +208,9 @@ pub trait Context {
|
||||||
|
|
||||||
/// Get the layout shape.
|
/// Get the layout shape.
|
||||||
fn layout_shape(&self, id: Layout) -> LayoutShape;
|
fn layout_shape(&self, id: Layout) -> LayoutShape;
|
||||||
|
|
||||||
|
/// Get a debug string representation of a place.
|
||||||
|
fn place_debug(&self, place: &Place) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A thread local variable that stores a pointer to the tables mapping between TyCtxt
|
// A thread local variable that stores a pointer to the tables mapping between TyCtxt
|
||||||
|
|
|
@ -27,7 +27,6 @@ use crate::compiler_interface::with;
|
||||||
pub use crate::crate_def::CrateDef;
|
pub use crate::crate_def::CrateDef;
|
||||||
pub use crate::crate_def::DefId;
|
pub use crate::crate_def::DefId;
|
||||||
pub use crate::error::*;
|
pub use crate::error::*;
|
||||||
use crate::mir::pretty::function_name;
|
|
||||||
use crate::mir::Body;
|
use crate::mir::Body;
|
||||||
use crate::mir::Mutability;
|
use crate::mir::Mutability;
|
||||||
use crate::ty::{ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty};
|
use crate::ty::{ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty};
|
||||||
|
@ -148,9 +147,8 @@ impl CrateItem {
|
||||||
with(|cx| cx.is_foreign_item(self.0))
|
with(|cx| cx.is_foreign_item(self.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
|
pub fn emit_mir<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
|
||||||
writeln!(w, "{}", function_name(*self))?;
|
self.body().dump(w, &self.name())
|
||||||
self.body().dump(w)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use crate::mir::pretty::{function_body, pretty_statement, pretty_terminator};
|
use crate::mir::pretty::function_body;
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind,
|
AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind,
|
||||||
VariantIdx,
|
VariantIdx,
|
||||||
};
|
};
|
||||||
use crate::{Error, Opaque, Span, Symbol};
|
use crate::{Error, Opaque, Span, Symbol};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
/// The SMIR representation of a single function.
|
/// The SMIR representation of a single function.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Body {
|
pub struct Body {
|
||||||
|
@ -90,28 +91,8 @@ impl Body {
|
||||||
self.locals.iter().enumerate()
|
self.locals.iter().enumerate()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
|
pub(crate) fn dump<W: io::Write>(&self, w: &mut W, fn_name: &str) -> io::Result<()> {
|
||||||
writeln!(w, "{}", function_body(self))?;
|
function_body(w, self, fn_name)
|
||||||
self.blocks
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(index, block)| -> io::Result<()> {
|
|
||||||
writeln!(w, " bb{}: {{", index)?;
|
|
||||||
let _ = block
|
|
||||||
.statements
|
|
||||||
.iter()
|
|
||||||
.map(|statement| -> io::Result<()> {
|
|
||||||
writeln!(w, "{}", pretty_statement(&statement.kind))?;
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
pretty_terminator(&block.terminator.kind, w)?;
|
|
||||||
writeln!(w, "").unwrap();
|
|
||||||
writeln!(w, " }}").unwrap();
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spread_arg(&self) -> Option<Local> {
|
pub fn spread_arg(&self) -> Option<Local> {
|
||||||
|
@ -674,7 +655,7 @@ pub enum Operand {
|
||||||
Constant(Constant),
|
Constant(Constant),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
pub struct Place {
|
pub struct Place {
|
||||||
pub local: Local,
|
pub local: Local,
|
||||||
/// projection out of a place (access a field, deref a pointer, etc)
|
/// projection out of a place (access a field, deref a pointer, etc)
|
||||||
|
|
|
@ -1,185 +1,193 @@
|
||||||
use crate::crate_def::CrateDef;
|
use crate::mir::{Operand, Place, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents};
|
||||||
use crate::mir::{Operand, Rvalue, StatementKind, UnwindAction};
|
use crate::ty::{Const, IndexedVal, Ty};
|
||||||
use crate::ty::{DynKind, FloatTy, IntTy, RigidTy, TyKind, UintTy};
|
use crate::{with, Body, Mutability};
|
||||||
use crate::{with, Body, CrateItem, Mutability};
|
use fmt::{Display, Formatter};
|
||||||
|
use std::fmt::Debug;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::{io, iter};
|
use std::{fmt, io, iter};
|
||||||
|
|
||||||
use super::{AssertMessage, BinOp, TerminatorKind};
|
use super::{AssertMessage, BinOp, TerminatorKind};
|
||||||
|
|
||||||
pub fn function_name(item: CrateItem) -> String {
|
use super::BorrowKind;
|
||||||
let mut pretty_name = String::new();
|
|
||||||
let body = item.body();
|
impl Display for Ty {
|
||||||
pretty_name.push_str("fn ");
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
pretty_name.push_str(item.name().as_str());
|
with(|ctx| write!(f, "{}", ctx.ty_pretty(*self)))
|
||||||
if body.arg_locals().is_empty() {
|
|
||||||
pretty_name.push_str("()");
|
|
||||||
} else {
|
|
||||||
pretty_name.push_str("(");
|
|
||||||
}
|
}
|
||||||
body.arg_locals().iter().enumerate().for_each(|(index, local)| {
|
}
|
||||||
pretty_name.push_str(format!("_{}: ", index).as_str());
|
|
||||||
pretty_name.push_str(&pretty_ty(local.ty.kind()));
|
impl Debug for Place {
|
||||||
});
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
if !body.arg_locals().is_empty() {
|
with(|ctx| write!(f, "{}", ctx.place_debug(self)))
|
||||||
pretty_name.push_str(")");
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn function_body<W: Write>(writer: &mut W, body: &Body, name: &str) -> io::Result<()> {
|
||||||
|
write!(writer, "fn {}(", name)?;
|
||||||
|
body.arg_locals()
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.try_for_each(|(index, local)| write!(writer, "_{}: {}", index + 1, local.ty))?;
|
||||||
|
write!(writer, ")")?;
|
||||||
|
|
||||||
let return_local = body.ret_local();
|
let return_local = body.ret_local();
|
||||||
pretty_name.push_str(" -> ");
|
writeln!(writer, " -> {} {{", return_local.ty)?;
|
||||||
pretty_name.push_str(&pretty_ty(return_local.ty.kind()));
|
|
||||||
pretty_name.push_str(" {");
|
body.locals().iter().enumerate().try_for_each(|(index, local)| -> io::Result<()> {
|
||||||
pretty_name
|
if index == 0 || index > body.arg_count {
|
||||||
|
writeln!(writer, " let {}_{}: {};", pretty_mut(local.mutability), index, local.ty)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
|
body.var_debug_info.iter().try_for_each(|info| {
|
||||||
|
let content = match &info.value {
|
||||||
|
VarDebugInfoContents::Place(place) => {
|
||||||
|
format!("{place:?}")
|
||||||
|
}
|
||||||
|
VarDebugInfoContents::Const(constant) => pretty_const(&constant.const_),
|
||||||
|
};
|
||||||
|
writeln!(writer, " debug {} => {};", info.name, content)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
body.blocks
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, block)| -> io::Result<()> {
|
||||||
|
writeln!(writer, " bb{}: {{", index)?;
|
||||||
|
let _ = block
|
||||||
|
.statements
|
||||||
|
.iter()
|
||||||
|
.map(|statement| -> io::Result<()> {
|
||||||
|
pretty_statement(writer, &statement.kind)?;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
pretty_terminator(writer, &block.terminator.kind)?;
|
||||||
|
writeln!(writer, " }}").unwrap();
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
writeln!(writer, "}}")?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn function_body(body: &Body) -> String {
|
fn pretty_statement<W: Write>(writer: &mut W, statement: &StatementKind) -> io::Result<()> {
|
||||||
let mut pretty_body = String::new();
|
|
||||||
body.inner_locals().iter().enumerate().for_each(|(index, local)| {
|
|
||||||
pretty_body.push_str(" ");
|
|
||||||
pretty_body.push_str(format!("let {}", ret_mutability(&local.mutability)).as_str());
|
|
||||||
pretty_body.push_str(format!("_{}: ", index).as_str());
|
|
||||||
pretty_body.push_str(format!("{}", pretty_ty(local.ty.kind())).as_str());
|
|
||||||
pretty_body.push_str(";\n");
|
|
||||||
});
|
|
||||||
pretty_body.push_str("}");
|
|
||||||
pretty_body
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ret_mutability(mutability: &Mutability) -> String {
|
|
||||||
match mutability {
|
|
||||||
Mutability::Not => "".to_string(),
|
|
||||||
Mutability::Mut => "mut ".to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pretty_statement(statement: &StatementKind) -> String {
|
|
||||||
let mut pretty = String::new();
|
|
||||||
match statement {
|
match statement {
|
||||||
StatementKind::Assign(place, rval) => {
|
StatementKind::Assign(place, rval) => {
|
||||||
pretty.push_str(format!(" _{} = ", place.local).as_str());
|
write!(writer, " {:?} = ", place)?;
|
||||||
pretty.push_str(format!("{}", &pretty_rvalue(rval)).as_str());
|
pretty_rvalue(writer, rval)?;
|
||||||
|
writeln!(writer, ";")
|
||||||
}
|
}
|
||||||
// FIXME: Add rest of the statements
|
// FIXME: Add rest of the statements
|
||||||
StatementKind::FakeRead(_, _) => {
|
StatementKind::FakeRead(cause, place) => {
|
||||||
return String::from("StatementKind::FakeRead:Unimplemented");
|
writeln!(writer, "FakeRead({cause:?}, {place:?});")
|
||||||
}
|
}
|
||||||
StatementKind::SetDiscriminant { .. } => {
|
StatementKind::SetDiscriminant { place, variant_index } => {
|
||||||
return String::from("StatementKind::SetDiscriminant:Unimplemented");
|
writeln!(writer, "discriminant({place:?} = {};", variant_index.to_index())
|
||||||
}
|
}
|
||||||
StatementKind::Deinit(_) => return String::from("StatementKind::Deinit:Unimplemented"),
|
StatementKind::Deinit(place) => writeln!(writer, "Deinit({place:?};"),
|
||||||
StatementKind::StorageLive(_) => {
|
StatementKind::StorageLive(local) => {
|
||||||
return String::from("StatementKind::StorageLive:Unimplemented");
|
writeln!(writer, "StorageLive(_{local});")
|
||||||
}
|
}
|
||||||
StatementKind::StorageDead(_) => {
|
StatementKind::StorageDead(local) => {
|
||||||
return String::from("StatementKind::StorageDead:Unimplemented");
|
writeln!(writer, "StorageDead(_{local});")
|
||||||
}
|
}
|
||||||
StatementKind::Retag(_, _) => return String::from("StatementKind::Retag:Unimplemented"),
|
StatementKind::Retag(kind, place) => writeln!(writer, "Retag({kind:?}, {place:?});"),
|
||||||
StatementKind::PlaceMention(_) => {
|
StatementKind::PlaceMention(place) => {
|
||||||
return String::from("StatementKind::PlaceMention:Unimplemented");
|
writeln!(writer, "PlaceMention({place:?};")
|
||||||
}
|
|
||||||
StatementKind::AscribeUserType { .. } => {
|
|
||||||
return String::from("StatementKind::AscribeUserType:Unimplemented");
|
|
||||||
}
|
|
||||||
StatementKind::Coverage(_) => return String::from("StatementKind::Coverage:Unimplemented"),
|
|
||||||
StatementKind::Intrinsic(_) => {
|
|
||||||
return String::from("StatementKind::Intrinsic:Unimplemented");
|
|
||||||
}
|
}
|
||||||
StatementKind::ConstEvalCounter => {
|
StatementKind::ConstEvalCounter => {
|
||||||
return String::from("StatementKind::ConstEvalCounter:Unimplemented");
|
writeln!(writer, "ConstEvalCounter;")
|
||||||
|
}
|
||||||
|
StatementKind::Nop => writeln!(writer, "nop;"),
|
||||||
|
StatementKind::AscribeUserType { .. }
|
||||||
|
| StatementKind::Coverage(_)
|
||||||
|
| StatementKind::Intrinsic(_) => {
|
||||||
|
// FIX-ME: Make them pretty.
|
||||||
|
writeln!(writer, "{statement:?};")
|
||||||
}
|
}
|
||||||
StatementKind::Nop => return String::from("StatementKind::Nop:Unimplemented"),
|
|
||||||
}
|
}
|
||||||
pretty
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pretty_terminator<W: io::Write>(terminator: &TerminatorKind, w: &mut W) -> io::Result<()> {
|
fn pretty_terminator<W: Write>(writer: &mut W, terminator: &TerminatorKind) -> io::Result<()> {
|
||||||
write!(w, "{}", pretty_terminator_head(terminator))?;
|
pretty_terminator_head(writer, terminator)?;
|
||||||
let successors = terminator.successors();
|
let successors = terminator.successors();
|
||||||
let successor_count = successors.len();
|
let successor_count = successors.len();
|
||||||
let labels = pretty_successor_labels(terminator);
|
let labels = pretty_successor_labels(terminator);
|
||||||
|
|
||||||
let show_unwind = !matches!(terminator.unwind(), None | Some(UnwindAction::Cleanup(_)));
|
let show_unwind = !matches!(terminator.unwind(), None | Some(UnwindAction::Cleanup(_)));
|
||||||
let fmt_unwind = |fmt: &mut dyn Write| -> io::Result<()> {
|
let fmt_unwind = |w: &mut W| -> io::Result<()> {
|
||||||
write!(fmt, "unwind ")?;
|
write!(w, "unwind ")?;
|
||||||
match terminator.unwind() {
|
match terminator.unwind() {
|
||||||
None | Some(UnwindAction::Cleanup(_)) => unreachable!(),
|
None | Some(UnwindAction::Cleanup(_)) => unreachable!(),
|
||||||
Some(UnwindAction::Continue) => write!(fmt, "continue"),
|
Some(UnwindAction::Continue) => write!(w, "continue"),
|
||||||
Some(UnwindAction::Unreachable) => write!(fmt, "unreachable"),
|
Some(UnwindAction::Unreachable) => write!(w, "unreachable"),
|
||||||
Some(UnwindAction::Terminate) => write!(fmt, "terminate"),
|
Some(UnwindAction::Terminate) => write!(w, "terminate"),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match (successor_count, show_unwind) {
|
match (successor_count, show_unwind) {
|
||||||
(0, false) => Ok(()),
|
(0, false) => {}
|
||||||
(0, true) => {
|
(0, true) => {
|
||||||
write!(w, " -> ")?;
|
write!(writer, " -> ")?;
|
||||||
fmt_unwind(w)?;
|
fmt_unwind(writer)?;
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
(1, false) => {
|
|
||||||
write!(w, " -> {:?}", successors[0])?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
(1, false) => write!(writer, " -> bb{:?}", successors[0])?,
|
||||||
_ => {
|
_ => {
|
||||||
write!(w, " -> [")?;
|
write!(writer, " -> [")?;
|
||||||
for (i, target) in successors.iter().enumerate() {
|
for (i, target) in successors.iter().enumerate() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
write!(w, ", ")?;
|
write!(writer, ", ")?;
|
||||||
}
|
}
|
||||||
write!(w, "{}: bb{:?}", labels[i], target)?;
|
write!(writer, "{}: bb{:?}", labels[i], target)?;
|
||||||
}
|
}
|
||||||
if show_unwind {
|
if show_unwind {
|
||||||
write!(w, ", ")?;
|
write!(writer, ", ")?;
|
||||||
fmt_unwind(w)?;
|
fmt_unwind(writer)?;
|
||||||
}
|
}
|
||||||
write!(w, "]")
|
write!(writer, "]")?;
|
||||||
}
|
}
|
||||||
}?;
|
};
|
||||||
|
|
||||||
Ok(())
|
writeln!(writer, ";")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pretty_terminator_head(terminator: &TerminatorKind) -> String {
|
fn pretty_terminator_head<W: Write>(writer: &mut W, terminator: &TerminatorKind) -> io::Result<()> {
|
||||||
use self::TerminatorKind::*;
|
use self::TerminatorKind::*;
|
||||||
let mut pretty = String::new();
|
const INDENT: &'static str = " ";
|
||||||
match terminator {
|
match terminator {
|
||||||
Goto { .. } => format!(" goto"),
|
Goto { .. } => write!(writer, "{INDENT}goto"),
|
||||||
SwitchInt { discr, .. } => {
|
SwitchInt { discr, .. } => {
|
||||||
format!(" switchInt(_{})", pretty_operand(discr))
|
write!(writer, "{INDENT}switchInt({})", pretty_operand(discr))
|
||||||
}
|
}
|
||||||
Resume => format!(" resume"),
|
Resume => write!(writer, "{INDENT}resume"),
|
||||||
Abort => format!(" abort"),
|
Abort => write!(writer, "{INDENT}abort"),
|
||||||
Return => format!(" return"),
|
Return => write!(writer, "{INDENT}return"),
|
||||||
Unreachable => format!(" unreachable"),
|
Unreachable => write!(writer, "{INDENT}unreachable"),
|
||||||
Drop { place, .. } => format!(" drop(_{:?})", place.local),
|
Drop { place, .. } => write!(writer, "{INDENT}drop({:?})", place),
|
||||||
Call { func, args, destination, .. } => {
|
Call { func, args, destination, .. } => {
|
||||||
pretty.push_str(" ");
|
write!(writer, "{INDENT}{:?} = {}(", destination, pretty_operand(func))?;
|
||||||
pretty.push_str(format!("_{} = ", destination.local).as_str());
|
let mut args_iter = args.iter();
|
||||||
pretty.push_str(&pretty_operand(func));
|
args_iter.next().map_or(Ok(()), |arg| write!(writer, "{}", pretty_operand(arg)))?;
|
||||||
pretty.push_str("(");
|
args_iter.try_for_each(|arg| write!(writer, ", {}", pretty_operand(arg)))?;
|
||||||
args.iter().enumerate().for_each(|(i, arg)| {
|
write!(writer, ")")
|
||||||
if i > 0 {
|
|
||||||
pretty.push_str(", ");
|
|
||||||
}
|
|
||||||
pretty.push_str(&pretty_operand(arg));
|
|
||||||
});
|
|
||||||
pretty.push_str(")");
|
|
||||||
pretty
|
|
||||||
}
|
}
|
||||||
Assert { cond, expected, msg, target: _, unwind: _ } => {
|
Assert { cond, expected, msg, target: _, unwind: _ } => {
|
||||||
pretty.push_str(" assert(");
|
write!(writer, "{INDENT}assert(")?;
|
||||||
if !expected {
|
if !expected {
|
||||||
pretty.push_str("!");
|
write!(writer, "!")?;
|
||||||
}
|
}
|
||||||
pretty.push_str(format!("{} bool),", &pretty_operand(cond)).as_str());
|
write!(writer, "{}, ", &pretty_operand(cond))?;
|
||||||
pretty.push_str(&pretty_assert_message(msg));
|
pretty_assert_message(writer, msg)?;
|
||||||
pretty.push_str(")");
|
write!(writer, ")")
|
||||||
pretty
|
|
||||||
}
|
}
|
||||||
InlineAsm { .. } => todo!(),
|
InlineAsm { .. } => write!(writer, "{INDENT}InlineAsm"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pretty_successor_labels(terminator: &TerminatorKind) -> Vec<String> {
|
fn pretty_successor_labels(terminator: &TerminatorKind) -> Vec<String> {
|
||||||
use self::TerminatorKind::*;
|
use self::TerminatorKind::*;
|
||||||
match terminator {
|
match terminator {
|
||||||
Resume | Abort | Return | Unreachable => vec![],
|
Resume | Abort | Return | Unreachable => vec![],
|
||||||
|
@ -201,283 +209,174 @@ pub fn pretty_successor_labels(terminator: &TerminatorKind) -> Vec<String> {
|
||||||
vec!["success".into(), "unwind".into()]
|
vec!["success".into(), "unwind".into()]
|
||||||
}
|
}
|
||||||
Assert { unwind: _, .. } => vec!["success".into()],
|
Assert { unwind: _, .. } => vec!["success".into()],
|
||||||
InlineAsm { .. } => todo!(),
|
InlineAsm { destination: Some(_), .. } => vec!["goto".into(), "unwind".into()],
|
||||||
|
InlineAsm { destination: None, .. } => vec!["unwind".into()],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pretty_assert_message(msg: &AssertMessage) -> String {
|
fn pretty_assert_message<W: Write>(writer: &mut W, msg: &AssertMessage) -> io::Result<()> {
|
||||||
let mut pretty = String::new();
|
|
||||||
match msg {
|
match msg {
|
||||||
AssertMessage::BoundsCheck { len, index } => {
|
AssertMessage::BoundsCheck { len, index } => {
|
||||||
let pretty_len = pretty_operand(len);
|
let pretty_len = pretty_operand(len);
|
||||||
let pretty_index = pretty_operand(index);
|
let pretty_index = pretty_operand(index);
|
||||||
pretty.push_str(format!("\"index out of bounds: the length is {{}} but the index is {{}}\", {pretty_len}, {pretty_index}").as_str());
|
write!(
|
||||||
pretty
|
writer,
|
||||||
|
"\"index out of bounds: the length is {{}} but the index is {{}}\", {pretty_len}, {pretty_index}"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
AssertMessage::Overflow(BinOp::Add, l, r) => {
|
AssertMessage::Overflow(BinOp::Add, l, r) => {
|
||||||
let pretty_l = pretty_operand(l);
|
let pretty_l = pretty_operand(l);
|
||||||
let pretty_r = pretty_operand(r);
|
let pretty_r = pretty_operand(r);
|
||||||
pretty.push_str(format!("\"attempt to compute `{{}} + {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
|
write!(
|
||||||
pretty
|
writer,
|
||||||
|
"\"attempt to compute `{{}} + {{}}`, which would overflow\", {pretty_l}, {pretty_r}"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
AssertMessage::Overflow(BinOp::Sub, l, r) => {
|
AssertMessage::Overflow(BinOp::Sub, l, r) => {
|
||||||
let pretty_l = pretty_operand(l);
|
let pretty_l = pretty_operand(l);
|
||||||
let pretty_r = pretty_operand(r);
|
let pretty_r = pretty_operand(r);
|
||||||
pretty.push_str(format!("\"attempt to compute `{{}} - {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
|
write!(
|
||||||
pretty
|
writer,
|
||||||
|
"\"attempt to compute `{{}} - {{}}`, which would overflow\", {pretty_l}, {pretty_r}"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
AssertMessage::Overflow(BinOp::Mul, l, r) => {
|
AssertMessage::Overflow(BinOp::Mul, l, r) => {
|
||||||
let pretty_l = pretty_operand(l);
|
let pretty_l = pretty_operand(l);
|
||||||
let pretty_r = pretty_operand(r);
|
let pretty_r = pretty_operand(r);
|
||||||
pretty.push_str(format!("\"attempt to compute `{{}} * {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
|
write!(
|
||||||
pretty
|
writer,
|
||||||
|
"\"attempt to compute `{{}} * {{}}`, which would overflow\", {pretty_l}, {pretty_r}"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
AssertMessage::Overflow(BinOp::Div, l, r) => {
|
AssertMessage::Overflow(BinOp::Div, l, r) => {
|
||||||
let pretty_l = pretty_operand(l);
|
let pretty_l = pretty_operand(l);
|
||||||
let pretty_r = pretty_operand(r);
|
let pretty_r = pretty_operand(r);
|
||||||
pretty.push_str(format!("\"attempt to compute `{{}} / {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
|
write!(
|
||||||
pretty
|
writer,
|
||||||
|
"\"attempt to compute `{{}} / {{}}`, which would overflow\", {pretty_l}, {pretty_r}"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
AssertMessage::Overflow(BinOp::Rem, l, r) => {
|
AssertMessage::Overflow(BinOp::Rem, l, r) => {
|
||||||
let pretty_l = pretty_operand(l);
|
let pretty_l = pretty_operand(l);
|
||||||
let pretty_r = pretty_operand(r);
|
let pretty_r = pretty_operand(r);
|
||||||
pretty.push_str(format!("\"attempt to compute `{{}} % {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
|
write!(
|
||||||
pretty
|
writer,
|
||||||
|
"\"attempt to compute `{{}} % {{}}`, which would overflow\", {pretty_l}, {pretty_r}"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
AssertMessage::Overflow(BinOp::Shr, _, r) => {
|
AssertMessage::Overflow(BinOp::Shr, _, r) => {
|
||||||
let pretty_r = pretty_operand(r);
|
let pretty_r = pretty_operand(r);
|
||||||
pretty.push_str(
|
write!(writer, "\"attempt to shift right by `{{}}`, which would overflow\", {pretty_r}")
|
||||||
format!("\"attempt to shift right by `{{}}`, which would overflow\", {pretty_r}")
|
|
||||||
.as_str(),
|
|
||||||
);
|
|
||||||
pretty
|
|
||||||
}
|
}
|
||||||
AssertMessage::Overflow(BinOp::Shl, _, r) => {
|
AssertMessage::Overflow(BinOp::Shl, _, r) => {
|
||||||
let pretty_r = pretty_operand(r);
|
let pretty_r = pretty_operand(r);
|
||||||
pretty.push_str(
|
write!(writer, "\"attempt to shift left by `{{}}`, which would overflow\", {pretty_r}")
|
||||||
format!("\"attempt to shift left by `{{}}`, which would overflow\", {pretty_r}")
|
|
||||||
.as_str(),
|
|
||||||
);
|
|
||||||
pretty
|
|
||||||
}
|
}
|
||||||
AssertMessage::Overflow(op, _, _) => unreachable!("`{:?}` cannot overflow", op),
|
AssertMessage::Overflow(op, _, _) => unreachable!("`{:?}` cannot overflow", op),
|
||||||
AssertMessage::OverflowNeg(op) => {
|
AssertMessage::OverflowNeg(op) => {
|
||||||
let pretty_op = pretty_operand(op);
|
let pretty_op = pretty_operand(op);
|
||||||
pretty.push_str(
|
write!(writer, "\"attempt to negate `{{}}`, which would overflow\", {pretty_op}")
|
||||||
format!("\"attempt to negate `{{}}`, which would overflow\", {pretty_op}").as_str(),
|
|
||||||
);
|
|
||||||
pretty
|
|
||||||
}
|
}
|
||||||
AssertMessage::DivisionByZero(op) => {
|
AssertMessage::DivisionByZero(op) => {
|
||||||
let pretty_op = pretty_operand(op);
|
let pretty_op = pretty_operand(op);
|
||||||
pretty.push_str(format!("\"attempt to divide `{{}}` by zero\", {pretty_op}").as_str());
|
write!(writer, "\"attempt to divide `{{}}` by zero\", {pretty_op}")
|
||||||
pretty
|
|
||||||
}
|
}
|
||||||
AssertMessage::RemainderByZero(op) => {
|
AssertMessage::RemainderByZero(op) => {
|
||||||
let pretty_op = pretty_operand(op);
|
let pretty_op = pretty_operand(op);
|
||||||
pretty.push_str(
|
write!(
|
||||||
format!("\"attempt to calculate the remainder of `{{}}` with a divisor of zero\", {pretty_op}").as_str(),
|
writer,
|
||||||
);
|
"\"attempt to calculate the remainder of `{{}}` with a divisor of zero\", {pretty_op}"
|
||||||
pretty
|
)
|
||||||
}
|
}
|
||||||
AssertMessage::MisalignedPointerDereference { required, found } => {
|
AssertMessage::MisalignedPointerDereference { required, found } => {
|
||||||
let pretty_required = pretty_operand(required);
|
let pretty_required = pretty_operand(required);
|
||||||
let pretty_found = pretty_operand(found);
|
let pretty_found = pretty_operand(found);
|
||||||
pretty.push_str(format!("\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\",{pretty_required}, {pretty_found}").as_str());
|
write!(
|
||||||
pretty
|
writer,
|
||||||
|
"\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\",{pretty_required}, {pretty_found}"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
AssertMessage::ResumedAfterReturn(_) | AssertMessage::ResumedAfterPanic(_) => {
|
AssertMessage::ResumedAfterReturn(_) | AssertMessage::ResumedAfterPanic(_) => {
|
||||||
msg.description().unwrap().to_string()
|
write!(writer, "{}", msg.description().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pretty_operand(operand: &Operand) -> String {
|
fn pretty_operand(operand: &Operand) -> String {
|
||||||
let mut pretty = String::new();
|
|
||||||
match operand {
|
match operand {
|
||||||
Operand::Copy(copy) => {
|
Operand::Copy(copy) => {
|
||||||
pretty.push_str("");
|
format!("{:?}", copy)
|
||||||
pretty.push_str(format!("{}", copy.local).as_str());
|
|
||||||
}
|
}
|
||||||
Operand::Move(mv) => {
|
Operand::Move(mv) => {
|
||||||
pretty.push_str("move ");
|
format!("move {:?}", mv)
|
||||||
pretty.push_str(format!("_{}", mv.local).as_str());
|
|
||||||
}
|
|
||||||
Operand::Constant(cnst) => {
|
|
||||||
pretty.push_str("const ");
|
|
||||||
pretty.push_str(with(|cx| cx.const_literal(&cnst.literal)).as_str());
|
|
||||||
}
|
}
|
||||||
|
Operand::Constant(cnst) => pretty_const(&cnst.literal),
|
||||||
}
|
}
|
||||||
pretty
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pretty_rvalue(rval: &Rvalue) -> String {
|
fn pretty_const(literal: &Const) -> String {
|
||||||
let mut pretty = String::new();
|
with(|cx| cx.const_pretty(&literal))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> {
|
||||||
match rval {
|
match rval {
|
||||||
Rvalue::AddressOf(muta, addr) => {
|
Rvalue::AddressOf(mutability, place) => {
|
||||||
pretty.push_str("&raw ");
|
write!(writer, "&raw {}(*{:?})", &pretty_mut(*mutability), place)
|
||||||
pretty.push_str(&ret_mutability(muta));
|
|
||||||
pretty.push_str(format!("(*_{})", addr.local).as_str());
|
|
||||||
}
|
}
|
||||||
Rvalue::Aggregate(aggregatekind, operands) => {
|
Rvalue::Aggregate(aggregate_kind, operands) => {
|
||||||
pretty.push_str(format!("{:#?}", aggregatekind).as_str());
|
// FIXME: Add pretty_aggregate function that returns a pretty string
|
||||||
pretty.push_str("(");
|
write!(writer, "{aggregate_kind:?} (")?;
|
||||||
operands.iter().enumerate().for_each(|(i, op)| {
|
let mut op_iter = operands.iter();
|
||||||
pretty.push_str(&pretty_operand(op));
|
op_iter.next().map_or(Ok(()), |op| write!(writer, "{}", pretty_operand(op)))?;
|
||||||
if i != operands.len() - 1 {
|
op_iter.try_for_each(|op| write!(writer, ", {}", pretty_operand(op)))?;
|
||||||
pretty.push_str(", ");
|
write!(writer, ")")
|
||||||
}
|
|
||||||
});
|
|
||||||
pretty.push_str(")");
|
|
||||||
}
|
}
|
||||||
Rvalue::BinaryOp(bin, op, op2) => {
|
Rvalue::BinaryOp(bin, op1, op2) => {
|
||||||
pretty.push_str(&pretty_operand(op));
|
write!(writer, "{:?}({}, {})", bin, &pretty_operand(op1), pretty_operand(op2))
|
||||||
pretty.push_str(" ");
|
|
||||||
pretty.push_str(format!("{:#?}", bin).as_str());
|
|
||||||
pretty.push_str(" ");
|
|
||||||
pretty.push_str(&pretty_operand(op2));
|
|
||||||
}
|
}
|
||||||
Rvalue::Cast(_, op, ty) => {
|
Rvalue::Cast(_, op, ty) => {
|
||||||
pretty.push_str(&pretty_operand(op));
|
write!(writer, "{} as {}", pretty_operand(op), ty)
|
||||||
pretty.push_str(" as ");
|
|
||||||
pretty.push_str(&pretty_ty(ty.kind()));
|
|
||||||
}
|
}
|
||||||
Rvalue::CheckedBinaryOp(bin, op1, op2) => {
|
Rvalue::CheckedBinaryOp(bin, op1, op2) => {
|
||||||
pretty.push_str(&pretty_operand(op1));
|
write!(writer, "Checked{:?}({}, {})", bin, &pretty_operand(op1), pretty_operand(op2))
|
||||||
pretty.push_str(" ");
|
|
||||||
pretty.push_str(format!("{:#?}", bin).as_str());
|
|
||||||
pretty.push_str(" ");
|
|
||||||
pretty.push_str(&pretty_operand(op2));
|
|
||||||
}
|
}
|
||||||
Rvalue::CopyForDeref(deref) => {
|
Rvalue::CopyForDeref(deref) => {
|
||||||
pretty.push_str("CopyForDeref");
|
write!(writer, "CopyForDeref({:?})", deref)
|
||||||
pretty.push_str(format!("{}", deref.local).as_str());
|
|
||||||
}
|
}
|
||||||
Rvalue::Discriminant(place) => {
|
Rvalue::Discriminant(place) => {
|
||||||
pretty.push_str("discriminant");
|
write!(writer, "discriminant({:?})", place)
|
||||||
pretty.push_str(format!("{}", place.local).as_str());
|
|
||||||
}
|
}
|
||||||
Rvalue::Len(len) => {
|
Rvalue::Len(len) => {
|
||||||
pretty.push_str("len");
|
write!(writer, "len({:?})", len)
|
||||||
pretty.push_str(format!("{}", len.local).as_str());
|
|
||||||
}
|
}
|
||||||
Rvalue::Ref(_, borrowkind, place) => {
|
Rvalue::Ref(_, borrowkind, place) => {
|
||||||
pretty.push_str("ref");
|
let kind = match borrowkind {
|
||||||
pretty.push_str(format!("{:#?}", borrowkind).as_str());
|
BorrowKind::Shared => "&",
|
||||||
pretty.push_str(format!("{}", place.local).as_str());
|
BorrowKind::Fake => "&fake ",
|
||||||
|
BorrowKind::Mut { .. } => "&mut ",
|
||||||
|
};
|
||||||
|
write!(writer, "{kind}{:?}", place)
|
||||||
}
|
}
|
||||||
Rvalue::Repeat(op, cnst) => {
|
Rvalue::Repeat(op, cnst) => {
|
||||||
pretty.push_str(&pretty_operand(op));
|
write!(writer, "{} \" \" {}", &pretty_operand(op), cnst.ty())
|
||||||
pretty.push_str(" ");
|
|
||||||
pretty.push_str(&pretty_ty(cnst.ty().kind()));
|
|
||||||
}
|
}
|
||||||
Rvalue::ShallowInitBox(_, _) => (),
|
Rvalue::ShallowInitBox(_, _) => Ok(()),
|
||||||
Rvalue::ThreadLocalRef(item) => {
|
Rvalue::ThreadLocalRef(item) => {
|
||||||
pretty.push_str("thread_local_ref");
|
write!(writer, "thread_local_ref{:?}", item)
|
||||||
pretty.push_str(format!("{:#?}", item).as_str());
|
|
||||||
}
|
}
|
||||||
Rvalue::NullaryOp(nul, ty) => {
|
Rvalue::NullaryOp(nul, ty) => {
|
||||||
pretty.push_str(format!("{:#?}", nul).as_str());
|
write!(writer, "{:?} {} \" \"", nul, ty)
|
||||||
pretty.push_str(&pretty_ty(ty.kind()));
|
|
||||||
pretty.push_str(" ");
|
|
||||||
}
|
}
|
||||||
Rvalue::UnaryOp(un, op) => {
|
Rvalue::UnaryOp(un, op) => {
|
||||||
pretty.push_str(&pretty_operand(op));
|
write!(writer, "{} \" \" {:?}", pretty_operand(op), un)
|
||||||
pretty.push_str(" ");
|
|
||||||
pretty.push_str(format!("{:#?}", un).as_str());
|
|
||||||
}
|
}
|
||||||
Rvalue::Use(op) => pretty.push_str(&pretty_operand(op)),
|
Rvalue::Use(op) => write!(writer, "{}", pretty_operand(op)),
|
||||||
}
|
}
|
||||||
pretty
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pretty_ty(ty: TyKind) -> String {
|
fn pretty_mut(mutability: Mutability) -> &'static str {
|
||||||
let mut pretty = String::new();
|
match mutability {
|
||||||
match ty {
|
Mutability::Not => " ",
|
||||||
TyKind::RigidTy(rigid_ty) => match rigid_ty {
|
Mutability::Mut => "mut ",
|
||||||
RigidTy::Bool => "bool".to_string(),
|
|
||||||
RigidTy::Char => "char".to_string(),
|
|
||||||
RigidTy::Int(i) => match i {
|
|
||||||
IntTy::Isize => "isize".to_string(),
|
|
||||||
IntTy::I8 => "i8".to_string(),
|
|
||||||
IntTy::I16 => "i16".to_string(),
|
|
||||||
IntTy::I32 => "i32".to_string(),
|
|
||||||
IntTy::I64 => "i64".to_string(),
|
|
||||||
IntTy::I128 => "i128".to_string(),
|
|
||||||
},
|
|
||||||
RigidTy::Uint(u) => match u {
|
|
||||||
UintTy::Usize => "usize".to_string(),
|
|
||||||
UintTy::U8 => "u8".to_string(),
|
|
||||||
UintTy::U16 => "u16".to_string(),
|
|
||||||
UintTy::U32 => "u32".to_string(),
|
|
||||||
UintTy::U64 => "u64".to_string(),
|
|
||||||
UintTy::U128 => "u128".to_string(),
|
|
||||||
},
|
|
||||||
RigidTy::Float(f) => match f {
|
|
||||||
FloatTy::F32 => "f32".to_string(),
|
|
||||||
FloatTy::F64 => "f64".to_string(),
|
|
||||||
},
|
|
||||||
RigidTy::Adt(def, _) => {
|
|
||||||
format!("{:#?}", with(|cx| cx.def_ty(def.0)))
|
|
||||||
}
|
|
||||||
RigidTy::Str => "str".to_string(),
|
|
||||||
RigidTy::Array(ty, len) => {
|
|
||||||
format!("[{}; {}]", pretty_ty(ty.kind()), with(|cx| cx.const_literal(&len)))
|
|
||||||
}
|
|
||||||
RigidTy::Slice(ty) => {
|
|
||||||
format!("[{}]", pretty_ty(ty.kind()))
|
|
||||||
}
|
|
||||||
RigidTy::RawPtr(ty, mutability) => {
|
|
||||||
pretty.push_str("*");
|
|
||||||
match mutability {
|
|
||||||
Mutability::Not => pretty.push_str("const "),
|
|
||||||
Mutability::Mut => pretty.push_str("mut "),
|
|
||||||
}
|
|
||||||
pretty.push_str(&pretty_ty(ty.kind()));
|
|
||||||
pretty
|
|
||||||
}
|
|
||||||
RigidTy::Ref(_, ty, mutability) => match mutability {
|
|
||||||
Mutability::Not => format!("&{}", pretty_ty(ty.kind())),
|
|
||||||
Mutability::Mut => format!("&mut {}", pretty_ty(ty.kind())),
|
|
||||||
},
|
|
||||||
RigidTy::FnDef(_, _) => format!("{:#?}", rigid_ty),
|
|
||||||
RigidTy::FnPtr(_) => format!("{:#?}", rigid_ty),
|
|
||||||
RigidTy::Closure(_, _) => format!("{:#?}", rigid_ty),
|
|
||||||
RigidTy::Coroutine(_, _, _) => format!("{:#?}", rigid_ty),
|
|
||||||
RigidTy::Dynamic(data, region, repr) => {
|
|
||||||
// FIXME: Fix binder printing, it looks ugly now
|
|
||||||
pretty.push_str("(");
|
|
||||||
match repr {
|
|
||||||
DynKind::Dyn => pretty.push_str("dyn "),
|
|
||||||
DynKind::DynStar => pretty.push_str("dyn* "),
|
|
||||||
}
|
|
||||||
pretty.push_str(format!("{:#?}", data).as_str());
|
|
||||||
pretty.push_str(format!(" + {:#?} )", region).as_str());
|
|
||||||
pretty
|
|
||||||
}
|
|
||||||
RigidTy::Never => "!".to_string(),
|
|
||||||
RigidTy::Tuple(tuple) => {
|
|
||||||
if tuple.is_empty() {
|
|
||||||
"()".to_string()
|
|
||||||
} else {
|
|
||||||
let mut tuple_str = String::new();
|
|
||||||
tuple_str.push_str("(");
|
|
||||||
tuple.iter().enumerate().for_each(|(i, ty)| {
|
|
||||||
tuple_str.push_str(&pretty_ty(ty.kind()));
|
|
||||||
if i != tuple.len() - 1 {
|
|
||||||
tuple_str.push_str(", ");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
tuple_str.push_str(")");
|
|
||||||
tuple_str
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => format!("{:#?}", rigid_ty),
|
|
||||||
},
|
|
||||||
TyKind::Alias(_, _) => format!("{:#?}", ty),
|
|
||||||
TyKind::Param(param_ty) => {
|
|
||||||
format!("{:#?}", param_ty.name)
|
|
||||||
}
|
|
||||||
TyKind::Bound(_, _) => format!("{:#?}", ty),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//@ check-pass
|
//@ check-pass
|
||||||
//@ only-x86_64
|
//@ only-x86_64
|
||||||
|
|
||||||
fn foo(i:i32) -> i32 {
|
fn foo(i: i32) -> i32 {
|
||||||
i + 1
|
i + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,4 +12,13 @@ fn bar(vec: &mut Vec<i32>) -> Vec<i32> {
|
||||||
new_vec
|
new_vec
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main(){}
|
pub fn demux(input: u8) -> u8 {
|
||||||
|
match input {
|
||||||
|
0 => 10,
|
||||||
|
1 => 6,
|
||||||
|
2 => 8,
|
||||||
|
_ => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
|
|
@ -1,234 +1,74 @@
|
||||||
// WARNING: This is highly experimental output it's intended for stable-mir developers only.
|
// WARNING: This is highly experimental output it's intended for stable-mir developers only.
|
||||||
// If you find a bug or want to improve the output open a issue at https://github.com/rust-lang/project-stable-mir.
|
// If you find a bug or want to improve the output open a issue at https://github.com/rust-lang/project-stable-mir.
|
||||||
fn foo(_0: i32) -> i32 {
|
fn foo(_1: i32) -> i32 {
|
||||||
let mut _0: (i32, bool);
|
let mut _0: i32;
|
||||||
}
|
let mut _2: (i32, bool);
|
||||||
|
debug i => _1;
|
||||||
bb0: {
|
bb0: {
|
||||||
_2 = 1 Add const 1_i32
|
_2 = CheckedAdd(_1, 1_i32);
|
||||||
assert(!move _2 bool),"attempt to compute `{} + {}`, which would overflow", 1, const 1_i32) -> [success: bb1, unwind continue]
|
assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", _1, 1_i32) -> [success: bb1, unwind continue];
|
||||||
}
|
}
|
||||||
bb1: {
|
bb1: {
|
||||||
_0 = move _2
|
_0 = move (_2.0: i32);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
fn bar(_0: &mut Ty {
|
|
||||||
id: 10,
|
|
||||||
kind: RigidTy(
|
|
||||||
Adt(
|
|
||||||
AdtDef(
|
|
||||||
DefId {
|
|
||||||
id: 3,
|
|
||||||
name: "std::vec::Vec",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
GenericArgs(
|
|
||||||
[
|
|
||||||
Type(
|
|
||||||
Ty {
|
|
||||||
id: 11,
|
|
||||||
kind: Param(
|
|
||||||
ParamTy {
|
|
||||||
index: 0,
|
|
||||||
name: "T",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Type(
|
|
||||||
Ty {
|
|
||||||
id: 12,
|
|
||||||
kind: Param(
|
|
||||||
ParamTy {
|
|
||||||
index: 1,
|
|
||||||
name: "A",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
}) -> Ty {
|
|
||||||
id: 10,
|
|
||||||
kind: RigidTy(
|
|
||||||
Adt(
|
|
||||||
AdtDef(
|
|
||||||
DefId {
|
|
||||||
id: 3,
|
|
||||||
name: "std::vec::Vec",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
GenericArgs(
|
|
||||||
[
|
|
||||||
Type(
|
|
||||||
Ty {
|
|
||||||
id: 11,
|
|
||||||
kind: Param(
|
|
||||||
ParamTy {
|
|
||||||
index: 0,
|
|
||||||
name: "T",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Type(
|
|
||||||
Ty {
|
|
||||||
id: 12,
|
|
||||||
kind: Param(
|
|
||||||
ParamTy {
|
|
||||||
index: 1,
|
|
||||||
name: "A",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
} {
|
|
||||||
let mut _0: Ty {
|
|
||||||
id: 10,
|
|
||||||
kind: RigidTy(
|
|
||||||
Adt(
|
|
||||||
AdtDef(
|
|
||||||
DefId {
|
|
||||||
id: 3,
|
|
||||||
name: "std::vec::Vec",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
GenericArgs(
|
|
||||||
[
|
|
||||||
Type(
|
|
||||||
Ty {
|
|
||||||
id: 11,
|
|
||||||
kind: Param(
|
|
||||||
ParamTy {
|
|
||||||
index: 0,
|
|
||||||
name: "T",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Type(
|
|
||||||
Ty {
|
|
||||||
id: 12,
|
|
||||||
kind: Param(
|
|
||||||
ParamTy {
|
|
||||||
index: 1,
|
|
||||||
name: "A",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
let mut _1: &Ty {
|
|
||||||
id: 10,
|
|
||||||
kind: RigidTy(
|
|
||||||
Adt(
|
|
||||||
AdtDef(
|
|
||||||
DefId {
|
|
||||||
id: 3,
|
|
||||||
name: "std::vec::Vec",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
GenericArgs(
|
|
||||||
[
|
|
||||||
Type(
|
|
||||||
Ty {
|
|
||||||
id: 11,
|
|
||||||
kind: Param(
|
|
||||||
ParamTy {
|
|
||||||
index: 0,
|
|
||||||
name: "T",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Type(
|
|
||||||
Ty {
|
|
||||||
id: 12,
|
|
||||||
kind: Param(
|
|
||||||
ParamTy {
|
|
||||||
index: 1,
|
|
||||||
name: "A",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
let _2: ();
|
|
||||||
let mut _3: &mut Ty {
|
|
||||||
id: 10,
|
|
||||||
kind: RigidTy(
|
|
||||||
Adt(
|
|
||||||
AdtDef(
|
|
||||||
DefId {
|
|
||||||
id: 3,
|
|
||||||
name: "std::vec::Vec",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
GenericArgs(
|
|
||||||
[
|
|
||||||
Type(
|
|
||||||
Ty {
|
|
||||||
id: 11,
|
|
||||||
kind: Param(
|
|
||||||
ParamTy {
|
|
||||||
index: 0,
|
|
||||||
name: "T",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Type(
|
|
||||||
Ty {
|
|
||||||
id: 12,
|
|
||||||
kind: Param(
|
|
||||||
ParamTy {
|
|
||||||
index: 1,
|
|
||||||
name: "A",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
fn bar(_1: &mut Vec<i32>) -> Vec<i32> {
|
||||||
|
let mut _0: Vec<i32>;
|
||||||
|
let mut _2: Vec<i32>;
|
||||||
|
let mut _3: &Vec<i32>;
|
||||||
|
let _4: ();
|
||||||
|
let mut _5: &mut Vec<i32>;
|
||||||
|
debug vec => _1;
|
||||||
|
debug new_vec => _2;
|
||||||
bb0: {
|
bb0: {
|
||||||
_3 = refShared1
|
_3 = &(*_1);
|
||||||
_2 = const <Vec<i32> as Clone>::clone(move _3) -> [return: bb1, unwind continue]
|
_2 = <Vec<i32> as Clone>::clone(move _3) -> [return: bb1, unwind continue];
|
||||||
}
|
}
|
||||||
bb1: {
|
bb1: {
|
||||||
_5 = refMut {
|
_5 = &mut _2;
|
||||||
kind: TwoPhaseBorrow,
|
_4 = Vec::<i32>::push(move _5, 1_i32) -> [return: bb2, unwind: bb3];
|
||||||
}2
|
|
||||||
_4 = const Vec::<i32>::push(move _5, const 1_i32) -> [return: bb2, unwind: bb3]
|
|
||||||
}
|
}
|
||||||
bb2: {
|
bb2: {
|
||||||
_0 = move _2
|
_0 = move _2;
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
bb3: {
|
bb3: {
|
||||||
drop(_2) -> [return: bb4, unwind terminate]
|
drop(_2) -> [return: bb4, unwind terminate];
|
||||||
}
|
}
|
||||||
bb4: {
|
bb4: {
|
||||||
resume
|
resume;
|
||||||
}
|
}
|
||||||
fn main() -> () {
|
|
||||||
}
|
}
|
||||||
|
fn demux(_1: u8) -> u8 {
|
||||||
|
let mut _0: u8;
|
||||||
|
debug input => _1;
|
||||||
bb0: {
|
bb0: {
|
||||||
return
|
switchInt(_1) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
|
||||||
}
|
}
|
||||||
|
bb1: {
|
||||||
|
_0 = 0_u8;
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
bb2: {
|
||||||
|
_0 = 10_u8;
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
bb3: {
|
||||||
|
_0 = 6_u8;
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
bb4: {
|
||||||
|
_0 = 8_u8;
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
bb5: {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn main() -> () {
|
||||||
|
let mut _0: ();
|
||||||
|
bb0: {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue