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