11
11
use middle:: const_eval:: ConstVal ;
12
12
use middle:: def_id:: DefId ;
13
13
use middle:: subst:: Substs ;
14
- use middle:: ty:: { AdtDef , ClosureSubsts , FnOutput , Region , Ty } ;
14
+ use middle:: ty:: { self , AdtDef , ClosureSubsts , FnOutput , Region , Ty } ;
15
15
use rustc_back:: slice;
16
16
use rustc_data_structures:: tuple_slice:: TupleSlice ;
17
17
use rustc_front:: hir:: InlineAsm ;
18
18
use syntax:: ast:: Name ;
19
19
use syntax:: codemap:: Span ;
20
- use std:: fmt:: { Debug , Formatter , Error } ;
21
- use std:: u32;
20
+ use std:: borrow:: { Cow , IntoCow } ;
21
+ use std:: fmt:: { Debug , Formatter , Error , Write } ;
22
+ use std:: { iter, u32} ;
22
23
23
24
/// Lowered representation of a single function.
24
25
#[ derive( RustcEncodable , RustcDecodable ) ]
@@ -317,31 +318,81 @@ impl<'tcx> BasicBlockData<'tcx> {
317
318
318
319
impl < ' tcx > Debug for Terminator < ' tcx > {
319
320
fn fmt ( & self , fmt : & mut Formatter ) -> Result < ( ) , Error > {
321
+ try!( self . fmt_head ( fmt) ) ;
322
+ let successors = self . successors ( ) ;
323
+ let labels = self . fmt_successor_labels ( ) ;
324
+ assert_eq ! ( successors. len( ) , labels. len( ) ) ;
325
+
326
+ match successors. len ( ) {
327
+ 0 => Ok ( ( ) ) ,
328
+
329
+ 1 => write ! ( fmt, " -> {:?}" , successors[ 0 ] ) ,
330
+
331
+ _ => {
332
+ try!( write ! ( fmt, " -> [" ) ) ;
333
+ for ( i, target) in successors. iter ( ) . enumerate ( ) {
334
+ if i > 0 {
335
+ try!( write ! ( fmt, ", " ) ) ;
336
+ }
337
+ try!( write ! ( fmt, "{}: {:?}" , labels[ i] , target) ) ;
338
+ }
339
+ write ! ( fmt, "]" )
340
+ }
341
+
342
+ }
343
+ }
344
+ }
345
+
346
+ impl < ' tcx > Terminator < ' tcx > {
347
+ /// Write the "head" part of the terminator; that is, its name and the data it uses to pick the
348
+ /// successor basic block, if any. The only information not inlcuded is the list of possible
349
+ /// successors, which may be rendered differently between the text and the graphviz format.
350
+ pub fn fmt_head < W : Write > ( & self , fmt : & mut W ) -> Result < ( ) , Error > {
320
351
use self :: Terminator :: * ;
321
352
match * self {
322
- Goto { target } =>
323
- write ! ( fmt, "goto -> {:?}" , target) ,
324
- Panic { target } =>
325
- write ! ( fmt, "panic -> {:?}" , target) ,
326
- If { cond : ref lv, ref targets } =>
327
- write ! ( fmt, "if({:?}) -> {:?}" , lv, targets) ,
328
- Switch { discr : ref lv, adt_def : _, ref targets } =>
329
- write ! ( fmt, "switch({:?}) -> {:?}" , lv, targets) ,
330
- SwitchInt { discr : ref lv, switch_ty : _, ref values, ref targets } =>
331
- write ! ( fmt, "switchInt({:?}, {:?}) -> {:?}" , lv, values, targets) ,
332
- Diverge =>
333
- write ! ( fmt, "diverge" ) ,
334
- Return =>
335
- write ! ( fmt, "return" ) ,
336
- Call { data : ref c, targets } => {
353
+ Goto { .. } => write ! ( fmt, "goto" ) ,
354
+ Panic { .. } => write ! ( fmt, "panic" ) ,
355
+ If { cond : ref lv, .. } => write ! ( fmt, "if({:?})" , lv) ,
356
+ Switch { discr : ref lv, .. } => write ! ( fmt, "switch({:?})" , lv) ,
357
+ SwitchInt { discr : ref lv, .. } => write ! ( fmt, "switchInt({:?})" , lv) ,
358
+ Diverge => write ! ( fmt, "diverge" ) ,
359
+ Return => write ! ( fmt, "return" ) ,
360
+ Call { data : ref c, .. } => {
337
361
try!( write ! ( fmt, "{:?} = {:?}(" , c. destination, c. func) ) ;
338
362
for ( index, arg) in c. args . iter ( ) . enumerate ( ) {
339
363
if index > 0 {
340
364
try!( write ! ( fmt, ", " ) ) ;
341
365
}
342
366
try!( write ! ( fmt, "{:?}" , arg) ) ;
343
367
}
344
- write ! ( fmt, ") -> {:?}" , targets)
368
+ write ! ( fmt, ")" )
369
+ }
370
+ }
371
+ }
372
+
373
+ /// Return the list of labels for the edges to the successor basic blocks.
374
+ pub fn fmt_successor_labels ( & self ) -> Vec < Cow < ' static , str > > {
375
+ use self :: Terminator :: * ;
376
+ match * self {
377
+ Diverge | Return => vec ! [ ] ,
378
+ Goto { .. } | Panic { .. } => vec ! [ "" . into_cow( ) ] ,
379
+ If { .. } => vec ! [ "true" . into_cow( ) , "false" . into_cow( ) ] ,
380
+ Call { .. } => vec ! [ "return" . into_cow( ) , "unwind" . into_cow( ) ] ,
381
+ Switch { ref adt_def, .. } => {
382
+ adt_def. variants
383
+ . iter ( )
384
+ . map ( |variant| variant. name . to_string ( ) . into_cow ( ) )
385
+ . collect ( )
386
+ }
387
+ SwitchInt { ref values, .. } => {
388
+ values. iter ( )
389
+ . map ( |const_val| {
390
+ let mut buf = String :: new ( ) ;
391
+ fmt_const_val ( & mut buf, const_val) . unwrap ( ) ;
392
+ buf. into_cow ( )
393
+ } )
394
+ . chain ( iter:: once ( String :: from ( "otherwise" ) . into_cow ( ) ) )
395
+ . collect ( )
345
396
}
346
397
}
347
398
}
@@ -495,19 +546,19 @@ impl<'tcx> Debug for Lvalue<'tcx> {
495
546
496
547
match * self {
497
548
Var ( id) =>
498
- write ! ( fmt, "Var( {:?}) " , id) ,
549
+ write ! ( fmt, "var {:?}" , id) ,
499
550
Arg ( id) =>
500
- write ! ( fmt, "Arg( {:?}) " , id) ,
551
+ write ! ( fmt, "arg {:?}" , id) ,
501
552
Temp ( id) =>
502
- write ! ( fmt, "Temp( {:?}) " , id) ,
553
+ write ! ( fmt, "tmp {:?}" , id) ,
503
554
Static ( id) =>
504
555
write ! ( fmt, "Static({:?})" , id) ,
505
556
ReturnPointer =>
506
557
write ! ( fmt, "ReturnPointer" ) ,
507
558
Projection ( ref data) =>
508
559
match data. elem {
509
- ProjectionElem :: Downcast ( _ , variant_index ) =>
510
- write ! ( fmt, "({:?} as {:? })" , data. base, variant_index ) ,
560
+ ProjectionElem :: Downcast ( ref adt_def , index ) =>
561
+ write ! ( fmt, "({:?} as {})" , data. base, adt_def . variants [ index ] . name ) ,
511
562
ProjectionElem :: Deref =>
512
563
write ! ( fmt, "(*{:?})" , data. base) ,
513
564
ProjectionElem :: Field ( field) =>
@@ -671,12 +722,12 @@ impl<'tcx> Debug for Rvalue<'tcx> {
671
722
Use ( ref lvalue) => write ! ( fmt, "{:?}" , lvalue) ,
672
723
Repeat ( ref a, ref b) => write ! ( fmt, "[{:?}; {:?}]" , a, b) ,
673
724
Ref ( ref a, bk, ref b) => write ! ( fmt, "&{:?} {:?} {:?}" , a, bk, b) ,
674
- Len ( ref a) => write ! ( fmt, "LEN ({:?})" , a) ,
675
- Cast ( ref kind, ref lv, ref ty) => write ! ( fmt, "{:?} as {:?} ({:?}" , lv, ty, kind) ,
676
- BinaryOp ( ref op, ref a, ref b) => write ! ( fmt, "{:?}({:?},{:?})" , op, a, b) ,
725
+ Len ( ref a) => write ! ( fmt, "Len ({:?})" , a) ,
726
+ Cast ( ref kind, ref lv, ref ty) => write ! ( fmt, "{:?} as {:?} ({:?}) " , lv, ty, kind) ,
727
+ BinaryOp ( ref op, ref a, ref b) => write ! ( fmt, "{:?}({:?}, {:?})" , op, a, b) ,
677
728
UnaryOp ( ref op, ref a) => write ! ( fmt, "{:?}({:?})" , op, a) ,
678
- Box ( ref t) => write ! ( fmt, "Box {:?}" , t) ,
679
- Aggregate ( ref kind, ref lvs) => write ! ( fmt, "Aggregate<{:?}>( {:?}) " , kind, lvs) ,
729
+ Box ( ref t) => write ! ( fmt, "Box( {:?}) " , t) ,
730
+ Aggregate ( ref kind, ref lvs) => write ! ( fmt, "Aggregate<{:?}>{:?}" , kind, lvs) ,
680
731
InlineAsm ( ref asm) => write ! ( fmt, "InlineAsm({:?})" , asm) ,
681
732
Slice { ref input, from_start, from_end } =>
682
733
write ! ( fmt, "{:?}[{:?}..-{:?}]" , input, from_start, from_end) ,
@@ -691,7 +742,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
691
742
// this does not necessarily mean that they are "==" in Rust -- in
692
743
// particular one must be wary of `NaN`!
693
744
694
- #[ derive( Clone , Debug , PartialEq , RustcEncodable , RustcDecodable ) ]
745
+ #[ derive( Clone , PartialEq , RustcEncodable , RustcDecodable ) ]
695
746
pub struct Constant < ' tcx > {
696
747
pub span : Span ,
697
748
pub ty : Ty < ' tcx > ,
@@ -707,7 +758,7 @@ pub enum ItemKind {
707
758
Method ,
708
759
}
709
760
710
- #[ derive( Clone , Debug , PartialEq , RustcEncodable , RustcDecodable ) ]
761
+ #[ derive( Clone , PartialEq , RustcEncodable , RustcDecodable ) ]
711
762
pub enum Literal < ' tcx > {
712
763
Item {
713
764
def_id : DefId ,
@@ -718,3 +769,38 @@ pub enum Literal<'tcx> {
718
769
value : ConstVal ,
719
770
} ,
720
771
}
772
+
773
+ impl < ' tcx > Debug for Constant < ' tcx > {
774
+ fn fmt ( & self , fmt : & mut Formatter ) -> Result < ( ) , Error > {
775
+ write ! ( fmt, "{:?}" , self . literal)
776
+ }
777
+ }
778
+
779
+ impl < ' tcx > Debug for Literal < ' tcx > {
780
+ fn fmt ( & self , fmt : & mut Formatter ) -> Result < ( ) , Error > {
781
+ use self :: Literal :: * ;
782
+ match * self {
783
+ Item { def_id, .. } =>
784
+ write ! ( fmt, "{}" , ty:: tls:: with( |tcx| tcx. item_path_str( def_id) ) ) ,
785
+ Value { ref value } => fmt_const_val ( fmt, value) ,
786
+ }
787
+ }
788
+ }
789
+
790
+ /// Write a `ConstVal` in a way closer to the original source code than the `Debug` output.
791
+ pub fn fmt_const_val < W : Write > ( fmt : & mut W , const_val : & ConstVal ) -> Result < ( ) , Error > {
792
+ use middle:: const_eval:: ConstVal :: * ;
793
+ match * const_val {
794
+ Float ( f) => write ! ( fmt, "{:?}" , f) ,
795
+ Int ( n) => write ! ( fmt, "{:?}" , n) ,
796
+ Uint ( n) => write ! ( fmt, "{:?}" , n) ,
797
+ Str ( ref s) => write ! ( fmt, "Str({:?})" , s) ,
798
+ ByteStr ( ref bytes) => write ! ( fmt, "ByteStr{:?}" , bytes) ,
799
+ Bool ( b) => write ! ( fmt, "{:?}" , b) ,
800
+ Struct ( id) => write ! ( fmt, "Struct({:?})" , id) ,
801
+ Tuple ( id) => write ! ( fmt, "Tuple({:?})" , id) ,
802
+ Function ( def_id) => write ! ( fmt, "Function({:?})" , def_id) ,
803
+ Array ( id, n) => write ! ( fmt, "Array({:?}, {:?})" , id, n) ,
804
+ Repeat ( id, n) => write ! ( fmt, "Repeat({:?}, {:?})" , id, n) ,
805
+ }
806
+ }
0 commit comments