11use crate :: crate_def:: CrateDef ;
2- use crate :: mir:: { Operand , Rvalue , StatementKind } ;
2+ use crate :: mir:: { Operand , Rvalue , StatementKind , UnwindAction } ;
33use crate :: ty:: { DynKind , FloatTy , IntTy , RigidTy , TyKind , UintTy } ;
44use crate :: { with, Body , CrateItem , Mutability } ;
5+ use std:: io:: Write ;
6+ use std:: { io, iter} ;
57
68use super :: { AssertMessage , BinOp , TerminatorKind } ;
79
@@ -72,21 +74,68 @@ pub fn pretty_statement(statement: &StatementKind) -> String {
7274 pretty
7375}
7476
75- pub fn pretty_terminator ( terminator : & TerminatorKind ) -> String {
77+ pub fn pretty_terminator < W : io:: Write > ( terminator : & TerminatorKind , w : & mut W ) -> io:: Result < ( ) > {
78+ write ! ( w, "{}" , pretty_terminator_head( terminator) ) ?;
79+ let successor_count = terminator. successors ( ) . count ( ) ;
80+ let labels = pretty_successor_labels ( terminator) ;
81+
82+ let show_unwind = !matches ! ( terminator. unwind( ) , None | Some ( UnwindAction :: Cleanup ( _) ) ) ;
83+ let fmt_unwind = |fmt : & mut dyn Write | -> io:: Result < ( ) > {
84+ write ! ( fmt, "unwind " ) ?;
85+ match terminator. unwind ( ) {
86+ None | Some ( UnwindAction :: Cleanup ( _) ) => unreachable ! ( ) ,
87+ Some ( UnwindAction :: Continue ) => write ! ( fmt, "continue" ) ,
88+ Some ( UnwindAction :: Unreachable ) => write ! ( fmt, "unreachable" ) ,
89+ Some ( UnwindAction :: Terminate ) => write ! ( fmt, "terminate" ) ,
90+ }
91+ } ;
92+
93+ match ( successor_count, show_unwind) {
94+ ( 0 , false ) => Ok ( ( ) ) ,
95+ ( 0 , true ) => {
96+ write ! ( w, " -> " ) ?;
97+ fmt_unwind ( w) ?;
98+ Ok ( ( ) )
99+ }
100+ ( 1 , false ) => {
101+ write ! ( w, " -> {:?}" , terminator. successors( ) . next( ) . unwrap( ) ) ?;
102+ Ok ( ( ) )
103+ }
104+ _ => {
105+ write ! ( w, " -> [" ) ?;
106+ for ( i, target) in terminator. successors ( ) . enumerate ( ) {
107+ if i > 0 {
108+ write ! ( w, ", " ) ?;
109+ }
110+ write ! ( w, "{}: {:?}" , labels[ i] , target) ?;
111+ }
112+ if show_unwind {
113+ write ! ( w, ", " ) ?;
114+ fmt_unwind ( w) ?;
115+ }
116+ write ! ( w, "]" )
117+ }
118+ } ?;
119+
120+ Ok ( ( ) )
121+ }
122+
123+ pub fn pretty_terminator_head ( terminator : & TerminatorKind ) -> String {
124+ use self :: TerminatorKind :: * ;
76125 let mut pretty = String :: new ( ) ;
77126 match terminator {
78- TerminatorKind :: Goto { .. } => format ! ( " goto" ) ,
79- TerminatorKind :: SwitchInt { discr, .. } => {
127+ Goto { .. } => format ! ( " goto" ) ,
128+ SwitchInt { discr, .. } => {
80129 format ! ( " switch({})" , pretty_operand( discr) )
81130 }
82- TerminatorKind :: Resume => format ! ( " resume" ) ,
83- TerminatorKind :: Abort => format ! ( " abort" ) ,
84- TerminatorKind :: Return => format ! ( " return" ) ,
85- TerminatorKind :: Unreachable => format ! ( " unreachable" ) ,
86- TerminatorKind :: Drop { place, .. } => format ! ( " drop({:?})" , place. local) ,
87- TerminatorKind :: Call { func, args, destination, .. } => {
131+ Resume => format ! ( " resume" ) ,
132+ Abort => format ! ( " abort" ) ,
133+ Return => format ! ( " return" ) ,
134+ Unreachable => format ! ( " unreachable" ) ,
135+ Drop { place, .. } => format ! ( " drop(_ {:?})" , place. local) ,
136+ Call { func, args, destination, .. } => {
88137 pretty. push_str ( " " ) ;
89- pretty. push_str ( format ! ( "{} = " , destination. local) . as_str ( ) ) ;
138+ pretty. push_str ( format ! ( "_ {} = " , destination. local) . as_str ( ) ) ;
90139 pretty. push_str ( & pretty_operand ( func) ) ;
91140 pretty. push_str ( "(" ) ;
92141 args. iter ( ) . enumerate ( ) . for_each ( |( i, arg) | {
@@ -98,18 +147,45 @@ pub fn pretty_terminator(terminator: &TerminatorKind) -> String {
98147 pretty. push_str ( ")" ) ;
99148 pretty
100149 }
101- TerminatorKind :: Assert { cond, expected, msg, target : _, unwind : _ } => {
150+ Assert { cond, expected, msg, target : _, unwind : _ } => {
102151 pretty. push_str ( " assert(" ) ;
103152 if !expected {
104153 pretty. push_str ( "!" ) ;
105154 }
106- pretty. push_str ( & pretty_operand ( cond) ) ;
155+ pretty. push_str ( format ! ( "{} bool)," , & pretty_operand( cond) ) . as_str ( ) ) ;
107156 pretty. push_str ( & pretty_assert_message ( msg) ) ;
108157 pretty. push_str ( ")" ) ;
109158 pretty
110159 }
111- TerminatorKind :: CoroutineDrop => format ! ( " coroutine_drop" ) ,
112- TerminatorKind :: InlineAsm { .. } => todo ! ( ) ,
160+ CoroutineDrop => format ! ( " coroutine_drop" ) ,
161+ InlineAsm { .. } => todo ! ( ) ,
162+ }
163+ }
164+
165+ pub fn pretty_successor_labels ( terminator : & TerminatorKind ) -> Vec < String > {
166+ use self :: TerminatorKind :: * ;
167+ match terminator {
168+ Resume | Abort | Return | Unreachable | CoroutineDrop => vec ! [ ] ,
169+ Goto { .. } => vec ! [ "" . to_string( ) ] ,
170+ SwitchInt { targets, .. } => targets
171+ . value
172+ . iter ( )
173+ . map ( |target| format ! ( "{}" , target) )
174+ . chain ( iter:: once ( "otherwise" . into ( ) ) )
175+ . collect ( ) ,
176+ Drop { unwind : UnwindAction :: Cleanup ( _) , .. } => vec ! [ "return" . into( ) , "unwind" . into( ) ] ,
177+ Drop { unwind : _, .. } => vec ! [ "return" . into( ) ] ,
178+ Call { target : Some ( _) , unwind : UnwindAction :: Cleanup ( _) , .. } => {
179+ vec ! [ "return" . into( ) , "unwind" . into( ) ]
180+ }
181+ Call { target : Some ( _) , unwind : _, .. } => vec ! [ "return" . into( ) ] ,
182+ Call { target : None , unwind : UnwindAction :: Cleanup ( _) , .. } => vec ! [ "unwind" . into( ) ] ,
183+ Call { target : None , unwind : _, .. } => vec ! [ ] ,
184+ Assert { unwind : UnwindAction :: Cleanup ( _) , .. } => {
185+ vec ! [ "success" . into( ) , "unwind" . into( ) ]
186+ }
187+ Assert { unwind : _, .. } => vec ! [ "success" . into( ) ] ,
188+ InlineAsm { .. } => todo ! ( ) ,
113189 }
114190}
115191
0 commit comments