about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_smir/src/rustc_internal/internal.rs46
-rw-r--r--compiler/rustc_smir/src/rustc_internal/pretty.rs2
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs15
-rw-r--r--compiler/stable_mir/src/compiler_interface.rs10
-rw-r--r--compiler/stable_mir/src/lib.rs6
-rw-r--r--compiler/stable_mir/src/mir/body.rs30
-rw-r--r--compiler/stable_mir/src/mir/mono.rs6
-rw-r--r--compiler/stable_mir/src/mir/pretty.rs521
-rw-r--r--tests/ui/stable-mir-print/basic_function.rs13
-rw-r--r--tests/ui/stable-mir-print/basic_function.stdout266
10 files changed, 355 insertions, 560 deletions
diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs
index 2cc9bc31873..bf7346be31f 100644
--- a/compiler/rustc_smir/src/rustc_internal/internal.rs
+++ b/compiler/rustc_smir/src/rustc_internal/internal.rs
@@ -10,7 +10,7 @@ use rustc_span::Symbol;
 use stable_mir::abi::Layout;
 use stable_mir::mir::alloc::AllocId;
 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::{
     Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const,
     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
 where
     T: RustcInternal,
diff --git a/compiler/rustc_smir/src/rustc_internal/pretty.rs b/compiler/rustc_smir/src/rustc_internal/pretty.rs
index 3ef2d28ea47..c0dce08b0d3 100644
--- a/compiler/rustc_smir/src/rustc_internal/pretty.rs
+++ b/compiler/rustc_smir/src/rustc_internal/pretty.rs
@@ -14,7 +14,7 @@ pub fn write_smir_pretty<'tcx, W: io::Write>(tcx: TyCtxt<'tcx>, w: &mut W) -> io
     )?;
     let _ = run(tcx, || {
         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(())
 }
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index d427e5fb88d..d39a3788d4c 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -19,7 +19,7 @@ use stable_mir::abi::{FnAbi, Layout, LayoutShape};
 use stable_mir::compiler_interface::Context;
 use stable_mir::mir::alloc::GlobalAlloc;
 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::ty::{
     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)
     }
 
-    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 tcx = tables.tcx;
         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)
     }
 
+    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 {
         let mut tables = self.0.borrow_mut();
         tables.types[ty].kind().stable(&mut *tables)
@@ -654,6 +659,12 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let tcx = tables.tcx;
         id.internal(&mut *tables, tcx).0.stable(&mut *tables)
     }
+
+    fn place_pretty(&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>>);
diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs
index f53dbcfbd96..8ed34fab54d 100644
--- a/compiler/stable_mir/src/compiler_interface.rs
+++ b/compiler/stable_mir/src/compiler_interface.rs
@@ -8,7 +8,7 @@ use std::cell::Cell;
 use crate::abi::{FnAbi, Layout, LayoutShape};
 use crate::mir::alloc::{AllocId, GlobalAlloc};
 use crate::mir::mono::{Instance, InstanceDef, StaticDef};
-use crate::mir::Body;
+use crate::mir::{Body, Place};
 use crate::target::MachineInfo;
 use crate::ty::{
     AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
@@ -126,12 +126,15 @@ pub trait Context {
     fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty;
 
     /// 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
     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.
     fn ty_kind(&self, ty: Ty) -> TyKind;
 
     // Get the discriminant Ty for this Ty if there's one.
@@ -205,6 +208,9 @@ pub trait Context {
 
     /// Get the layout shape.
     fn layout_shape(&self, id: Layout) -> LayoutShape;
+
+    /// Get a debug string representation of a place.
+    fn place_pretty(&self, place: &Place) -> String;
 }
 
 // A thread local variable that stores a pointer to the tables mapping between TyCtxt
diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs
index d849c834ae0..d1a2948ea77 100644
--- a/compiler/stable_mir/src/lib.rs
+++ b/compiler/stable_mir/src/lib.rs
@@ -27,7 +27,6 @@ use crate::compiler_interface::with;
 pub use crate::crate_def::CrateDef;
 pub use crate::crate_def::DefId;
 pub use crate::error::*;
-use crate::mir::pretty::function_name;
 use crate::mir::Body;
 use crate::mir::Mutability;
 use crate::ty::{ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty};
@@ -148,9 +147,8 @@ impl CrateItem {
         with(|cx| cx.is_foreign_item(self.0))
     }
 
-    pub fn dump<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
-        writeln!(w, "{}", function_name(*self))?;
-        self.body().dump(w)
+    pub fn emit_mir<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
+        self.body().dump(w, &self.name())
     }
 }
 
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index ae8e71bb950..e4a012d8c47 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -1,10 +1,11 @@
-use crate::mir::pretty::{function_body, pretty_statement, pretty_terminator};
+use crate::mir::pretty::function_body;
 use crate::ty::{
     AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind,
     VariantIdx,
 };
 use crate::{Error, Opaque, Span, Symbol};
 use std::io;
+
 /// The SMIR representation of a single function.
 #[derive(Clone, Debug)]
 pub struct Body {
@@ -90,28 +91,9 @@ impl Body {
         self.locals.iter().enumerate()
     }
 
-    pub fn dump<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
-        writeln!(w, "{}", function_body(self))?;
-        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(())
+    /// Emit the body using the provided name for the signature.
+    pub fn dump<W: io::Write>(&self, w: &mut W, fn_name: &str) -> io::Result<()> {
+        function_body(w, self, fn_name)
     }
 
     pub fn spread_arg(&self) -> Option<Local> {
@@ -674,7 +656,7 @@ pub enum Operand {
     Constant(Constant),
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Eq, PartialEq)]
 pub struct Place {
     pub local: Local,
     /// projection out of a place (access a field, deref a pointer, etc)
diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs
index 38e5776c48c..aafa89c03e0 100644
--- a/compiler/stable_mir/src/mir/mono.rs
+++ b/compiler/stable_mir/src/mir/mono.rs
@@ -4,6 +4,7 @@ use crate::mir::Body;
 use crate::ty::{Allocation, ClosureDef, ClosureKind, FnDef, GenericArgs, IndexedVal, Ty};
 use crate::{with, CrateItem, DefId, Error, ItemKind, Opaque, Symbol};
 use std::fmt::{Debug, Formatter};
+use std::io;
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub enum MonoItem {
@@ -157,6 +158,11 @@ impl Instance {
     pub fn try_const_eval(&self, const_ty: Ty) -> Result<Allocation, Error> {
         with(|cx| cx.eval_instance(self.def, const_ty))
     }
+
+    /// Emit the body of this instance if it has one.
+    pub fn emit_mir<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
+        if let Some(body) = self.body() { body.dump(w, &self.name()) } else { Ok(()) }
+    }
 }
 
 impl Debug for Instance {
diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs
index 8b7b488d312..4ac4833add7 100644
--- a/compiler/stable_mir/src/mir/pretty.rs
+++ b/compiler/stable_mir/src/mir/pretty.rs
@@ -1,185 +1,193 @@
-use crate::crate_def::CrateDef;
-use crate::mir::{Operand, Rvalue, StatementKind, UnwindAction};
-use crate::ty::{DynKind, FloatTy, IntTy, RigidTy, TyKind, UintTy};
-use crate::{with, Body, CrateItem, Mutability};
+use crate::mir::{Operand, Place, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents};
+use crate::ty::{Const, IndexedVal, Ty};
+use crate::{with, Body, Mutability};
+use fmt::{Display, Formatter};
+use std::fmt::Debug;
 use std::io::Write;
-use std::{io, iter};
+use std::{fmt, io, iter};
 
 use super::{AssertMessage, BinOp, TerminatorKind};
 
-pub fn function_name(item: CrateItem) -> String {
-    let mut pretty_name = String::new();
-    let body = item.body();
-    pretty_name.push_str("fn ");
-    pretty_name.push_str(item.name().as_str());
-    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()));
-    });
-    if !body.arg_locals().is_empty() {
-        pretty_name.push_str(")");
+use super::BorrowKind;
+
+impl Display for Ty {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        with(|ctx| write!(f, "{}", ctx.ty_pretty(*self)))
     }
-    let return_local = body.ret_local();
-    pretty_name.push_str(" -> ");
-    pretty_name.push_str(&pretty_ty(return_local.ty.kind()));
-    pretty_name.push_str(" {");
-    pretty_name
 }
 
-pub fn function_body(body: &Body) -> String {
-    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
+impl Debug for Place {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        with(|ctx| write!(f, "{}", ctx.place_pretty(self)))
+    }
 }
 
-pub fn ret_mutability(mutability: &Mutability) -> String {
-    match mutability {
-        Mutability::Not => "".to_string(),
-        Mutability::Mut => "mut ".to_string(),
-    }
+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();
+    writeln!(writer, " -> {} {{", return_local.ty)?;
+
+    body.locals().iter().enumerate().try_for_each(|(index, local)| -> io::Result<()> {
+        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 pretty_statement(statement: &StatementKind) -> String {
-    let mut pretty = String::new();
+fn pretty_statement<W: Write>(writer: &mut W, statement: &StatementKind) -> io::Result<()> {
     match statement {
         StatementKind::Assign(place, rval) => {
-            pretty.push_str(format!("        _{} = ", place.local).as_str());
-            pretty.push_str(format!("{}", &pretty_rvalue(rval)).as_str());
+            write!(writer, "        {:?} = ", place)?;
+            pretty_rvalue(writer, rval)?;
+            writeln!(writer, ";")
         }
         // FIXME: Add rest of the statements
-        StatementKind::FakeRead(_, _) => {
-            return String::from("StatementKind::FakeRead:Unimplemented");
+        StatementKind::FakeRead(cause, place) => {
+            writeln!(writer, "FakeRead({cause:?}, {place:?});")
         }
-        StatementKind::SetDiscriminant { .. } => {
-            return String::from("StatementKind::SetDiscriminant:Unimplemented");
+        StatementKind::SetDiscriminant { place, variant_index } => {
+            writeln!(writer, "discriminant({place:?} = {};", variant_index.to_index())
         }
-        StatementKind::Deinit(_) => return String::from("StatementKind::Deinit:Unimplemented"),
-        StatementKind::StorageLive(_) => {
-            return String::from("StatementKind::StorageLive:Unimplemented");
+        StatementKind::Deinit(place) => writeln!(writer, "Deinit({place:?};"),
+        StatementKind::StorageLive(local) => {
+            writeln!(writer, "StorageLive(_{local});")
         }
-        StatementKind::StorageDead(_) => {
-            return String::from("StatementKind::StorageDead:Unimplemented");
+        StatementKind::StorageDead(local) => {
+            writeln!(writer, "StorageDead(_{local});")
         }
-        StatementKind::Retag(_, _) => return String::from("StatementKind::Retag:Unimplemented"),
-        StatementKind::PlaceMention(_) => {
-            return String::from("StatementKind::PlaceMention:Unimplemented");
-        }
-        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::Retag(kind, place) => writeln!(writer, "Retag({kind:?}, {place:?});"),
+        StatementKind::PlaceMention(place) => {
+            writeln!(writer, "PlaceMention({place:?};")
         }
         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<()> {
-    write!(w, "{}", pretty_terminator_head(terminator))?;
+fn pretty_terminator<W: Write>(writer: &mut W, terminator: &TerminatorKind) -> io::Result<()> {
+    pretty_terminator_head(writer, terminator)?;
     let successors = terminator.successors();
     let successor_count = successors.len();
     let labels = pretty_successor_labels(terminator);
 
     let show_unwind = !matches!(terminator.unwind(), None | Some(UnwindAction::Cleanup(_)));
-    let fmt_unwind = |fmt: &mut dyn Write| -> io::Result<()> {
-        write!(fmt, "unwind ")?;
+    let fmt_unwind = |w: &mut W| -> io::Result<()> {
+        write!(w, "unwind ")?;
         match terminator.unwind() {
             None | Some(UnwindAction::Cleanup(_)) => unreachable!(),
-            Some(UnwindAction::Continue) => write!(fmt, "continue"),
-            Some(UnwindAction::Unreachable) => write!(fmt, "unreachable"),
-            Some(UnwindAction::Terminate) => write!(fmt, "terminate"),
+            Some(UnwindAction::Continue) => write!(w, "continue"),
+            Some(UnwindAction::Unreachable) => write!(w, "unreachable"),
+            Some(UnwindAction::Terminate) => write!(w, "terminate"),
         }
     };
 
     match (successor_count, show_unwind) {
-        (0, false) => Ok(()),
+        (0, false) => {}
         (0, true) => {
-            write!(w, " -> ")?;
-            fmt_unwind(w)?;
-            Ok(())
-        }
-        (1, false) => {
-            write!(w, " -> {:?}", successors[0])?;
-            Ok(())
+            write!(writer, " -> ")?;
+            fmt_unwind(writer)?;
         }
+        (1, false) => write!(writer, " -> bb{:?}", successors[0])?,
         _ => {
-            write!(w, " -> [")?;
+            write!(writer, " -> [")?;
             for (i, target) in successors.iter().enumerate() {
                 if i > 0 {
-                    write!(w, ", ")?;
+                    write!(writer, ", ")?;
                 }
-                write!(w, "{}: bb{:?}", labels[i], target)?;
+                write!(writer, "{}: bb{:?}", labels[i], target)?;
             }
             if show_unwind {
-                write!(w, ", ")?;
-                fmt_unwind(w)?;
+                write!(writer, ", ")?;
+                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::*;
-    let mut pretty = String::new();
+    const INDENT: &'static str = "        ";
     match terminator {
-        Goto { .. } => format!("        goto"),
+        Goto { .. } => write!(writer, "{INDENT}goto"),
         SwitchInt { discr, .. } => {
-            format!("        switchInt(_{})", pretty_operand(discr))
+            write!(writer, "{INDENT}switchInt({})", pretty_operand(discr))
         }
-        Resume => format!("        resume"),
-        Abort => format!("        abort"),
-        Return => format!("        return"),
-        Unreachable => format!("        unreachable"),
-        Drop { place, .. } => format!("        drop(_{:?})", place.local),
+        Resume => write!(writer, "{INDENT}resume"),
+        Abort => write!(writer, "{INDENT}abort"),
+        Return => write!(writer, "{INDENT}return"),
+        Unreachable => write!(writer, "{INDENT}unreachable"),
+        Drop { place, .. } => write!(writer, "{INDENT}drop({:?})", place),
         Call { func, args, destination, .. } => {
-            pretty.push_str("        ");
-            pretty.push_str(format!("_{} = ", destination.local).as_str());
-            pretty.push_str(&pretty_operand(func));
-            pretty.push_str("(");
-            args.iter().enumerate().for_each(|(i, arg)| {
-                if i > 0 {
-                    pretty.push_str(", ");
-                }
-                pretty.push_str(&pretty_operand(arg));
-            });
-            pretty.push_str(")");
-            pretty
+            write!(writer, "{INDENT}{:?} = {}(", destination, pretty_operand(func))?;
+            let mut args_iter = args.iter();
+            args_iter.next().map_or(Ok(()), |arg| write!(writer, "{}", pretty_operand(arg)))?;
+            args_iter.try_for_each(|arg| write!(writer, ", {}", pretty_operand(arg)))?;
+            write!(writer, ")")
         }
         Assert { cond, expected, msg, target: _, unwind: _ } => {
-            pretty.push_str("        assert(");
+            write!(writer, "{INDENT}assert(")?;
             if !expected {
-                pretty.push_str("!");
+                write!(writer, "!")?;
             }
-            pretty.push_str(format!("{} bool),", &pretty_operand(cond)).as_str());
-            pretty.push_str(&pretty_assert_message(msg));
-            pretty.push_str(")");
-            pretty
+            write!(writer, "{}, ", &pretty_operand(cond))?;
+            pretty_assert_message(writer, msg)?;
+            write!(writer, ")")
         }
-        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::*;
     match terminator {
         Resume | Abort | Return | Unreachable => vec![],
@@ -201,283 +209,174 @@ pub fn pretty_successor_labels(terminator: &TerminatorKind) -> Vec<String> {
             vec!["success".into(), "unwind".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 {
-    let mut pretty = String::new();
+fn pretty_assert_message<W: Write>(writer: &mut W, msg: &AssertMessage) -> io::Result<()> {
     match msg {
         AssertMessage::BoundsCheck { len, index } => {
             let pretty_len = pretty_operand(len);
             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());
-            pretty
+            write!(
+                writer,
+                "\"index out of bounds: the length is {{}} but the index is {{}}\", {pretty_len}, {pretty_index}"
+            )
         }
         AssertMessage::Overflow(BinOp::Add, l, r) => {
             let pretty_l = pretty_operand(l);
             let pretty_r = pretty_operand(r);
-            pretty.push_str(format!("\"attempt to compute `{{}} + {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
-            pretty
+            write!(
+                writer,
+                "\"attempt to compute `{{}} + {{}}`, which would overflow\", {pretty_l}, {pretty_r}"
+            )
         }
         AssertMessage::Overflow(BinOp::Sub, l, r) => {
             let pretty_l = pretty_operand(l);
             let pretty_r = pretty_operand(r);
-            pretty.push_str(format!("\"attempt to compute `{{}} - {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
-            pretty
+            write!(
+                writer,
+                "\"attempt to compute `{{}} - {{}}`, which would overflow\", {pretty_l}, {pretty_r}"
+            )
         }
         AssertMessage::Overflow(BinOp::Mul, l, r) => {
             let pretty_l = pretty_operand(l);
             let pretty_r = pretty_operand(r);
-            pretty.push_str(format!("\"attempt to compute `{{}} * {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
-            pretty
+            write!(
+                writer,
+                "\"attempt to compute `{{}} * {{}}`, which would overflow\", {pretty_l}, {pretty_r}"
+            )
         }
         AssertMessage::Overflow(BinOp::Div, l, r) => {
             let pretty_l = pretty_operand(l);
             let pretty_r = pretty_operand(r);
-            pretty.push_str(format!("\"attempt to compute `{{}} / {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
-            pretty
+            write!(
+                writer,
+                "\"attempt to compute `{{}} / {{}}`, which would overflow\", {pretty_l}, {pretty_r}"
+            )
         }
         AssertMessage::Overflow(BinOp::Rem, l, r) => {
             let pretty_l = pretty_operand(l);
             let pretty_r = pretty_operand(r);
-            pretty.push_str(format!("\"attempt to compute `{{}} % {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
-            pretty
+            write!(
+                writer,
+                "\"attempt to compute `{{}} % {{}}`, which would overflow\", {pretty_l}, {pretty_r}"
+            )
         }
         AssertMessage::Overflow(BinOp::Shr, _, r) => {
             let pretty_r = pretty_operand(r);
-            pretty.push_str(
-                format!("\"attempt to shift right by `{{}}`, which would overflow\", {pretty_r}")
-                    .as_str(),
-            );
-            pretty
+            write!(writer, "\"attempt to shift right by `{{}}`, which would overflow\", {pretty_r}")
         }
         AssertMessage::Overflow(BinOp::Shl, _, r) => {
             let pretty_r = pretty_operand(r);
-            pretty.push_str(
-                format!("\"attempt to shift left by `{{}}`, which would overflow\", {pretty_r}")
-                    .as_str(),
-            );
-            pretty
+            write!(writer, "\"attempt to shift left by `{{}}`, which would overflow\", {pretty_r}")
         }
         AssertMessage::Overflow(op, _, _) => unreachable!("`{:?}` cannot overflow", op),
         AssertMessage::OverflowNeg(op) => {
             let pretty_op = pretty_operand(op);
-            pretty.push_str(
-                format!("\"attempt to negate `{{}}`, which would overflow\", {pretty_op}").as_str(),
-            );
-            pretty
+            write!(writer, "\"attempt to negate `{{}}`, which would overflow\", {pretty_op}")
         }
         AssertMessage::DivisionByZero(op) => {
             let pretty_op = pretty_operand(op);
-            pretty.push_str(format!("\"attempt to divide `{{}}` by zero\", {pretty_op}").as_str());
-            pretty
+            write!(writer, "\"attempt to divide `{{}}` by zero\", {pretty_op}")
         }
         AssertMessage::RemainderByZero(op) => {
             let pretty_op = pretty_operand(op);
-            pretty.push_str(
-                format!("\"attempt to calculate the remainder of `{{}}` with a divisor of zero\", {pretty_op}").as_str(),
-            );
-            pretty
+            write!(
+                writer,
+                "\"attempt to calculate the remainder of `{{}}` with a divisor of zero\", {pretty_op}"
+            )
         }
         AssertMessage::MisalignedPointerDereference { required, found } => {
             let pretty_required = pretty_operand(required);
             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());
-            pretty
+            write!(
+                writer,
+                "\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\",{pretty_required}, {pretty_found}"
+            )
         }
         AssertMessage::ResumedAfterReturn(_) | AssertMessage::ResumedAfterPanic(_) => {
-            msg.description().unwrap().to_string()
+            write!(writer, "{}", msg.description().unwrap())
         }
     }
 }
 
-pub fn pretty_operand(operand: &Operand) -> String {
-    let mut pretty = String::new();
+fn pretty_operand(operand: &Operand) -> String {
     match operand {
         Operand::Copy(copy) => {
-            pretty.push_str("");
-            pretty.push_str(format!("{}", copy.local).as_str());
+            format!("{:?}", copy)
         }
         Operand::Move(mv) => {
-            pretty.push_str("move ");
-            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());
+            format!("move {:?}", mv)
         }
+        Operand::Constant(cnst) => pretty_const(&cnst.literal),
     }
-    pretty
 }
 
-pub fn pretty_rvalue(rval: &Rvalue) -> String {
-    let mut pretty = String::new();
+fn pretty_const(literal: &Const) -> String {
+    with(|cx| cx.const_pretty(&literal))
+}
+
+fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> {
     match rval {
-        Rvalue::AddressOf(muta, addr) => {
-            pretty.push_str("&raw ");
-            pretty.push_str(&ret_mutability(muta));
-            pretty.push_str(format!("(*_{})", addr.local).as_str());
-        }
-        Rvalue::Aggregate(aggregatekind, operands) => {
-            pretty.push_str(format!("{:#?}", aggregatekind).as_str());
-            pretty.push_str("(");
-            operands.iter().enumerate().for_each(|(i, op)| {
-                pretty.push_str(&pretty_operand(op));
-                if i != operands.len() - 1 {
-                    pretty.push_str(", ");
-                }
-            });
-            pretty.push_str(")");
+        Rvalue::AddressOf(mutability, place) => {
+            write!(writer, "&raw {}(*{:?})", &pretty_mut(*mutability), place)
         }
-        Rvalue::BinaryOp(bin, op, op2) => {
-            pretty.push_str(&pretty_operand(op));
-            pretty.push_str(" ");
-            pretty.push_str(format!("{:#?}", bin).as_str());
-            pretty.push_str(" ");
-            pretty.push_str(&pretty_operand(op2));
+        Rvalue::Aggregate(aggregate_kind, operands) => {
+            // FIXME: Add pretty_aggregate function that returns a pretty string
+            write!(writer, "{aggregate_kind:?} (")?;
+            let mut op_iter = operands.iter();
+            op_iter.next().map_or(Ok(()), |op| write!(writer, "{}", pretty_operand(op)))?;
+            op_iter.try_for_each(|op| write!(writer, ", {}", pretty_operand(op)))?;
+            write!(writer, ")")
+        }
+        Rvalue::BinaryOp(bin, op1, op2) => {
+            write!(writer, "{:?}({}, {})", bin, &pretty_operand(op1), pretty_operand(op2))
         }
         Rvalue::Cast(_, op, ty) => {
-            pretty.push_str(&pretty_operand(op));
-            pretty.push_str(" as ");
-            pretty.push_str(&pretty_ty(ty.kind()));
+            write!(writer, "{} as {}", pretty_operand(op), ty)
         }
         Rvalue::CheckedBinaryOp(bin, op1, op2) => {
-            pretty.push_str(&pretty_operand(op1));
-            pretty.push_str(" ");
-            pretty.push_str(format!("{:#?}", bin).as_str());
-            pretty.push_str(" ");
-            pretty.push_str(&pretty_operand(op2));
+            write!(writer, "Checked{:?}({}, {})", bin, &pretty_operand(op1), pretty_operand(op2))
         }
         Rvalue::CopyForDeref(deref) => {
-            pretty.push_str("CopyForDeref");
-            pretty.push_str(format!("{}", deref.local).as_str());
+            write!(writer, "CopyForDeref({:?})", deref)
         }
         Rvalue::Discriminant(place) => {
-            pretty.push_str("discriminant");
-            pretty.push_str(format!("{}", place.local).as_str());
+            write!(writer, "discriminant({:?})", place)
         }
         Rvalue::Len(len) => {
-            pretty.push_str("len");
-            pretty.push_str(format!("{}", len.local).as_str());
+            write!(writer, "len({:?})", len)
         }
         Rvalue::Ref(_, borrowkind, place) => {
-            pretty.push_str("ref");
-            pretty.push_str(format!("{:#?}", borrowkind).as_str());
-            pretty.push_str(format!("{}", place.local).as_str());
+            let kind = match borrowkind {
+                BorrowKind::Shared => "&",
+                BorrowKind::Fake => "&fake ",
+                BorrowKind::Mut { .. } => "&mut ",
+            };
+            write!(writer, "{kind}{:?}", place)
         }
         Rvalue::Repeat(op, cnst) => {
-            pretty.push_str(&pretty_operand(op));
-            pretty.push_str(" ");
-            pretty.push_str(&pretty_ty(cnst.ty().kind()));
+            write!(writer, "{} \" \" {}", &pretty_operand(op), cnst.ty())
         }
-        Rvalue::ShallowInitBox(_, _) => (),
+        Rvalue::ShallowInitBox(_, _) => Ok(()),
         Rvalue::ThreadLocalRef(item) => {
-            pretty.push_str("thread_local_ref");
-            pretty.push_str(format!("{:#?}", item).as_str());
+            write!(writer, "thread_local_ref{:?}", item)
         }
         Rvalue::NullaryOp(nul, ty) => {
-            pretty.push_str(format!("{:#?}", nul).as_str());
-            pretty.push_str(&pretty_ty(ty.kind()));
-            pretty.push_str(" ");
+            write!(writer, "{:?} {} \" \"", nul, ty)
         }
         Rvalue::UnaryOp(un, op) => {
-            pretty.push_str(&pretty_operand(op));
-            pretty.push_str(" ");
-            pretty.push_str(format!("{:#?}", un).as_str());
+            write!(writer, "{} \" \" {:?}", pretty_operand(op), un)
         }
-        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 {
-    let mut pretty = String::new();
-    match ty {
-        TyKind::RigidTy(rigid_ty) => match rigid_ty {
-            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),
+fn pretty_mut(mutability: Mutability) -> &'static str {
+    match mutability {
+        Mutability::Not => " ",
+        Mutability::Mut => "mut ",
     }
 }
diff --git a/tests/ui/stable-mir-print/basic_function.rs b/tests/ui/stable-mir-print/basic_function.rs
index 9b27a56dab1..deefef63bdb 100644
--- a/tests/ui/stable-mir-print/basic_function.rs
+++ b/tests/ui/stable-mir-print/basic_function.rs
@@ -2,7 +2,7 @@
 //@ check-pass
 //@ only-x86_64
 
-fn foo(i:i32) -> i32 {
+fn foo(i: i32) -> i32 {
     i + 1
 }
 
@@ -12,4 +12,13 @@ fn bar(vec: &mut Vec<i32>) -> Vec<i32> {
     new_vec
 }
 
-fn main(){}
+pub fn demux(input: u8) -> u8 {
+    match input {
+        0 => 10,
+        1 => 6,
+        2 => 8,
+        _ => 0,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/stable-mir-print/basic_function.stdout b/tests/ui/stable-mir-print/basic_function.stdout
index d9b33a4257c..3926c1048f5 100644
--- a/tests/ui/stable-mir-print/basic_function.stdout
+++ b/tests/ui/stable-mir-print/basic_function.stdout
@@ -1,234 +1,74 @@
 // 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.
-fn foo(_0: i32) -> i32 {
-    let mut _0: (i32, bool);
+fn foo(_1: i32) -> i32 {
+    let mut _0: i32;
+    let mut _2: (i32, bool);
+    debug i => _1;
+    bb0: {
+        _2 = CheckedAdd(_1, 1_i32);
+        assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", _1, 1_i32) -> [success: bb1, unwind continue];
+    }
+    bb1: {
+        _0 = move (_2.0: i32);
+        return;
+    }
 }
+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: {
-        _2 = 1 Add const 1_i32
-        assert(!move _2 bool),"attempt to compute `{} + {}`, which would overflow", 1, const 1_i32) -> [success: bb1, unwind continue]
+        _3 = &(*_1);
+        _2 = <Vec<i32> as Clone>::clone(move _3) -> [return: bb1, unwind continue];
     }
     bb1: {
-        _0 = move _2
-        return
+        _5 = &mut _2;
+        _4 = Vec::<i32>::push(move _5, 1_i32) -> [return: bb2, unwind: bb3];
+    }
+    bb2: {
+        _0 = move _2;
+        return;
+    }
+    bb3: {
+        drop(_2) -> [return: bb4, unwind terminate];
+    }
+    bb4: {
+        resume;
     }
-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 demux(_1: u8) -> u8 {
+    let mut _0: u8;
+    debug input => _1;
     bb0: {
-        _3 = refShared1
-        _2 = const <Vec<i32> as Clone>::clone(move _3) -> [return: bb1, unwind continue]
+        switchInt(_1) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
     }
     bb1: {
-        _5 = refMut {
-    kind: TwoPhaseBorrow,
-}2
-        _4 = const Vec::<i32>::push(move _5, const 1_i32) -> [return: bb2, unwind: bb3]
+        _0 = 0_u8;
+        goto -> bb5;
     }
     bb2: {
-        _0 = move _2
-        return
+        _0 = 10_u8;
+        goto -> bb5;
     }
     bb3: {
-        drop(_2) -> [return: bb4, unwind terminate]
+        _0 = 6_u8;
+        goto -> bb5;
     }
     bb4: {
-        resume
+        _0 = 8_u8;
+        goto -> bb5;
+    }
+    bb5: {
+        return;
     }
-fn main() -> () {
 }
+fn main() -> () {
+    let mut _0: ();
     bb0: {
-        return
+        return;
     }
+}