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 } ;
2
5
use crate :: ty:: { DynKind , FloatTy , IntTy , RigidTy , TyKind , UintTy } ;
3
6
use crate :: { with, Body , CrateItem , Mutability } ;
4
7
@@ -71,21 +74,68 @@ pub fn pretty_statement(statement: &StatementKind) -> String {
71
74
pretty
72
75
}
73
76
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 :: * ;
75
125
let mut pretty = String :: new ( ) ;
76
126
match terminator {
77
- TerminatorKind :: Goto { .. } => format ! ( " goto" ) ,
78
- TerminatorKind :: SwitchInt { discr, .. } => {
127
+ Goto { .. } => format ! ( " goto" ) ,
128
+ SwitchInt { discr, .. } => {
79
129
format ! ( " switch({})" , pretty_operand( discr) )
80
130
}
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, .. } => {
87
137
pretty. push_str ( " " ) ;
88
- pretty. push_str ( format ! ( "{} = " , destination. local) . as_str ( ) ) ;
138
+ pretty. push_str ( format ! ( "_ {} = " , destination. local) . as_str ( ) ) ;
89
139
pretty. push_str ( & pretty_operand ( func) ) ;
90
140
pretty. push_str ( "(" ) ;
91
141
args. iter ( ) . enumerate ( ) . for_each ( |( i, arg) | {
@@ -97,18 +147,45 @@ pub fn pretty_terminator(terminator: &TerminatorKind) -> String {
97
147
pretty. push_str ( ")" ) ;
98
148
pretty
99
149
}
100
- TerminatorKind :: Assert { cond, expected, msg, target : _, unwind : _ } => {
150
+ Assert { cond, expected, msg, target : _, unwind : _ } => {
101
151
pretty. push_str ( " assert(" ) ;
102
152
if !expected {
103
153
pretty. push_str ( "!" ) ;
104
154
}
105
- pretty. push_str ( & pretty_operand ( cond) ) ;
155
+ pretty. push_str ( format ! ( "{} bool)," , & pretty_operand( cond) ) . as_str ( ) ) ;
106
156
pretty. push_str ( & pretty_assert_message ( msg) ) ;
107
157
pretty. push_str ( ")" ) ;
108
158
pretty
109
159
}
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 ! ( ) ,
112
189
}
113
190
}
114
191
0 commit comments