1- use crate :: mir:: { Operand , Rvalue , StatementKind } ;
1+ use std:: io:: Write ;
2+ use std:: { io, iter} ;
3+
4+ use crate :: mir:: { Operand , Rvalue , StatementKind , UnwindAction } ;
25use crate :: ty:: { DynKind , FloatTy , IntTy , RigidTy , TyKind , UintTy } ;
36use crate :: { with, Body , CrateItem , Mutability } ;
47
@@ -71,21 +74,68 @@ pub fn pretty_statement(statement: &StatementKind) -> String {
7174 pretty
7275}
7376
74- 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 :: * ;
75125 let mut pretty = String :: new ( ) ;
76126 match terminator {
77- TerminatorKind :: Goto { .. } => format ! ( " goto" ) ,
78- TerminatorKind :: SwitchInt { discr, .. } => {
127+ Goto { .. } => format ! ( " goto" ) ,
128+ SwitchInt { discr, .. } => {
79129 format ! ( " switch({})" , pretty_operand( discr) )
80130 }
81- TerminatorKind :: Resume => format ! ( " resume" ) ,
82- TerminatorKind :: Abort => format ! ( " abort" ) ,
83- TerminatorKind :: Return => format ! ( " return" ) ,
84- TerminatorKind :: Unreachable => format ! ( " unreachable" ) ,
85- TerminatorKind :: Drop { place, .. } => format ! ( " drop({:?})" , place. local) ,
86- 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, .. } => {
87137 pretty. push_str ( " " ) ;
88- pretty. push_str ( format ! ( "{} = " , destination. local) . as_str ( ) ) ;
138+ pretty. push_str ( format ! ( "_ {} = " , destination. local) . as_str ( ) ) ;
89139 pretty. push_str ( & pretty_operand ( func) ) ;
90140 pretty. push_str ( "(" ) ;
91141 args. iter ( ) . enumerate ( ) . for_each ( |( i, arg) | {
@@ -97,18 +147,45 @@ pub fn pretty_terminator(terminator: &TerminatorKind) -> String {
97147 pretty. push_str ( ")" ) ;
98148 pretty
99149 }
100- TerminatorKind :: Assert { cond, expected, msg, target : _, unwind : _ } => {
150+ Assert { cond, expected, msg, target : _, unwind : _ } => {
101151 pretty. push_str ( " assert(" ) ;
102152 if !expected {
103153 pretty. push_str ( "!" ) ;
104154 }
105- pretty. push_str ( & pretty_operand ( cond) ) ;
155+ pretty. push_str ( format ! ( "{} bool)," , & pretty_operand( cond) ) . as_str ( ) ) ;
106156 pretty. push_str ( & pretty_assert_message ( msg) ) ;
107157 pretty. push_str ( ")" ) ;
108158 pretty
109159 }
110- TerminatorKind :: CoroutineDrop => format ! ( " coroutine_drop" ) ,
111- 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 ! ( ) ,
112189 }
113190}
114191
0 commit comments