diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index da7c2440faa..e9b5a328422 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -44,6 +44,7 @@ rustc_query_system = { path = "../rustc_query_system" } rustc_resolve = { path = "../rustc_resolve" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } +rustc_smir ={ path = "../rustc_smir" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index cc533b9941a..84f8941ff66 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -9,6 +9,7 @@ use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty}; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::{OutFileName, PpHirMode, PpMode, PpSourceMode}; use rustc_session::Session; +use rustc_smir::rustc_internal::pretty::write_smir_pretty; use rustc_span::symbol::Ident; use rustc_span::FileName; @@ -325,6 +326,11 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { write_mir_graphviz(ex.tcx(), None, &mut out).unwrap(); String::from_utf8(out).unwrap() } + Smir => { + let mut out = Vec::new(); + write_smir_pretty(ex.tcx(), &mut out).unwrap(); + String::from_utf8(out).unwrap() + } ThirTree => { let tcx = ex.tcx(); let mut out = String::new(); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index add40b83d21..54335645e43 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2926,6 +2926,7 @@ fn parse_pretty(handler: &EarlyErrorHandler, unstable_opts: &UnstableOptions) -> "thir-tree" => ThirTree, "thir-flat" => ThirFlat, "mir" => Mir, + "smir" => Smir, "mir-cfg" => MirCFG, name => handler.early_error(format!( "argument to `unpretty` must be one of `normal`, `identified`, \ @@ -3106,6 +3107,8 @@ pub enum PpMode { Mir, /// `-Zunpretty=mir-cfg` MirCFG, + /// `-Zunpretty=smir` + Smir, } impl PpMode { @@ -3122,7 +3125,8 @@ impl PpMode { | ThirTree | ThirFlat | Mir - | MirCFG => true, + | MirCFG + | Smir => true, } } pub fn needs_hir(&self) -> bool { @@ -3130,13 +3134,13 @@ impl PpMode { match *self { Source(_) | AstTree | AstTreeExpanded => false, - Hir(_) | HirTree | ThirTree | ThirFlat | Mir | MirCFG => true, + Hir(_) | HirTree | ThirTree | ThirFlat | Mir | MirCFG | Smir => true, } } pub fn needs_analysis(&self) -> bool { use PpMode::*; - matches!(*self, Hir(PpHirMode::Typed) | Mir | MirCFG | ThirTree | ThirFlat) + matches!(*self, Hir(PpHirMode::Typed) | Mir | Smir | MirCFG | ThirTree | ThirFlat) } } diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index c82f948f195..7957c3ce617 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -21,6 +21,7 @@ use std::hash::Hash; use std::ops::Index; mod internal; +pub mod pretty; pub fn stable<'tcx, S: Stable<'tcx>>(item: S) -> S::T { with_tables(|tables| item.stable(tables)) @@ -299,4 +300,10 @@ impl Index { type T; fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T; + + /// Use this when you want to convert to a rustc counterpart in user-code. + /// Do not use this within the smir crates themselves. + fn internal_via_tls(&self) -> Self::T { + with_tables(|tables| self.internal(tables)) + } } diff --git a/compiler/rustc_smir/src/rustc_internal/pretty.rs b/compiler/rustc_smir/src/rustc_internal/pretty.rs new file mode 100644 index 00000000000..e9af5081353 --- /dev/null +++ b/compiler/rustc_smir/src/rustc_internal/pretty.rs @@ -0,0 +1,133 @@ +use std::io; + +use rustc_middle::ty::TyCtxt; +use stable_mir::{ + ty::{RigidTy, TyKind}, + CrateItem, mir::Mutability, +}; + + +use super::{run, RustcInternal}; + +pub fn write_smir_pretty<'tcx>(tcx: TyCtxt<'tcx>, w: &mut dyn io::Write) -> io::Result<()> { + run(tcx, || { + let items = stable_mir::all_local_items(); + items.iter().for_each(|item| { + // Because we can't return a Result from a closure, we have to unwrap here. + writeln!(w, "{}", function_name(*item,tcx)).unwrap(); + writeln!(w, "{}", function_body(*item,tcx)).unwrap(); + }) + }); + Ok(()) +} + +pub fn function_name(item: CrateItem,tcx: TyCtxt<'_>) -> String { + let mut name = String::new(); + let body = item.body(); + name.push_str("fn "); + name.push_str(item.name().as_str()); + if body.arg_locals().is_empty() { + name.push_str("()"); + }else{ + name.push_str("("); + } + body.arg_locals().iter().for_each(|local| { + name.push_str(format!("_{}: ",local.local).as_str()); + name.push_str(&pretty_ty(local.ty.kind(), tcx)); + }); + if !body.arg_locals().is_empty() { + name.push_str(")"); + } + let return_local = body.ret_local(); + name.push_str(" -> "); + name.push_str(&pretty_ty(return_local.ty.kind(), tcx)); + name.push_str(" {"); + name +} + +pub fn function_body(item: CrateItem,_tcx: TyCtxt<'_>) -> String { + let mut body_str = String::new(); + let body = item.body(); + body.inner_locals().iter().for_each(|local| { + body_str.push_str(" "); + body_str.push_str(format!("let {}",ret_mutability(&local.mutability)).as_str()); + body_str.push_str(format!("_{}: ",local.local).as_str()); + body_str.push_str(format!("{}",pretty_ty(local.ty.kind(), _tcx)).as_str()); + body_str.push_str(";\n"); + + }); + body_str.push_str("}"); + body_str + +} + +pub fn ret_mutability(mutability: &Mutability) -> String { + match mutability { + Mutability::Not => "".to_string(), + Mutability::Mut => "mut ".to_string(), + } +} + +pub fn pretty_ty<'tcx>(ty: TyKind,tcx: TyCtxt<'tcx>) -> String { + let mut pretty = String::new(); + pretty.push_str(""); + match ty { + TyKind::RigidTy(rigid_ty) => match rigid_ty { + RigidTy::Bool => "bool".to_string(), + RigidTy::Char => "char".to_string(), + RigidTy::Int(i) => match i { + stable_mir::ty::IntTy::Isize => "isize".to_string(), + stable_mir::ty::IntTy::I8 => "i8".to_string(), + stable_mir::ty::IntTy::I16 => "i16".to_string(), + stable_mir::ty::IntTy::I32 => "i32".to_string(), + stable_mir::ty::IntTy::I64 => "i64".to_string(), + stable_mir::ty::IntTy::I128 => "i128".to_string(), + }, + RigidTy::Uint(u) => match u { + stable_mir::ty::UintTy::Usize => "usize".to_string(), + stable_mir::ty::UintTy::U8 => "u8".to_string(), + stable_mir::ty::UintTy::U16 => "u16".to_string(), + stable_mir::ty::UintTy::U32 => "u32".to_string(), + stable_mir::ty::UintTy::U64 => "u64".to_string(), + stable_mir::ty::UintTy::U128 => "u128".to_string(), + }, + RigidTy::Float(f) => match f { + stable_mir::ty::FloatTy::F32 => "f32".to_string(), + stable_mir::ty::FloatTy::F64 => "f64".to_string(), + }, + RigidTy::Adt(def, _) => format!("{:#?}", tcx.type_of(def.0.internal_via_tls()).instantiate_identity()), + RigidTy::Foreign(_) => format!("{:#?}", rigid_ty), + RigidTy::Str => "str".to_string(), + RigidTy::Array(_ty, len) => { + format!("[{};{:#?}]", 1,len.internal_via_tls())}, + RigidTy::Slice(ty) => pretty_ty(ty.kind(),tcx), + RigidTy::RawPtr(_, _) => format!("{:#?}", rigid_ty), + RigidTy::Ref(_, ty, _) => pretty_ty(ty.kind(),tcx), + RigidTy::FnDef(_, _) => format!("{:#?}", rigid_ty), + RigidTy::FnPtr(_) => format!("{:#?}", rigid_ty), + RigidTy::Closure(_, _) => format!("{:#?}", rigid_ty), + RigidTy::Coroutine(_, _, _) => format!("{:#?}", rigid_ty), + RigidTy::Dynamic(_, _, _) => format!("{:#?}", rigid_ty), + 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(),tcx)); + if i != tuple.len() - 1 { + tuple_str.push_str(", "); + } + }); + tuple_str.push_str(")"); + tuple_str + } + }, + }, + TyKind::Alias(_, _) => format!("{:#?}", ty), + TyKind::Param(_) => format!("{:#?}", ty), + TyKind::Bound(_, _) => format!("{:#?}", ty), + } +} diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 3df09cef1c7..69b0c0bb80d 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -400,10 +400,12 @@ impl<'tcx> Stable<'tcx> for mir::Body<'tcx> { }) .collect(), self.local_decls - .iter() - .map(|decl| stable_mir::mir::LocalDecl { + .iter_enumerated() + .map(|(local, decl)| stable_mir::mir::LocalDecl { ty: decl.ty.stable(tables), span: decl.source_info.span.stable(tables), + local: local.as_usize(), + mutability: decl.mutability.stable(tables), }) .collect(), self.arg_count, diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 351e7bb69c3..2981d6a8bb5 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -64,6 +64,8 @@ type LocalDecls = Vec; pub struct LocalDecl { pub ty: Ty, pub span: Span, + pub local: Local, + pub mutability: Mutability, } #[derive(Clone, Debug)]