1111use middle:: const_eval:: ConstVal ;
1212use middle:: def_id:: DefId ;
1313use middle:: subst:: Substs ;
14- use middle:: ty:: { AdtDef , ClosureSubsts , FnOutput , Region , Ty } ;
14+ use middle:: ty:: { self , AdtDef , ClosureSubsts , FnOutput , Region , Ty } ;
1515use rustc_back:: slice;
1616use rustc_data_structures:: tuple_slice:: TupleSlice ;
1717use rustc_front:: hir:: InlineAsm ;
1818use syntax:: ast:: Name ;
1919use 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} ;
2223
2324/// Lowered representation of a single function.
2425#[ derive( RustcEncodable , RustcDecodable ) ]
@@ -317,31 +318,81 @@ impl<'tcx> BasicBlockData<'tcx> {
317318
318319impl < ' tcx > Debug for Terminator < ' tcx > {
319320 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 > {
320351 use self :: Terminator :: * ;
321352 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, .. } => {
337361 try!( write ! ( fmt, "{:?} = {:?}(" , c. destination, c. func) ) ;
338362 for ( index, arg) in c. args . iter ( ) . enumerate ( ) {
339363 if index > 0 {
340364 try!( write ! ( fmt, ", " ) ) ;
341365 }
342366 try!( write ! ( fmt, "{:?}" , arg) ) ;
343367 }
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 ( )
345396 }
346397 }
347398 }
@@ -495,19 +546,19 @@ impl<'tcx> Debug for Lvalue<'tcx> {
495546
496547 match * self {
497548 Var ( id) =>
498- write ! ( fmt, "Var( {:?}) " , id) ,
549+ write ! ( fmt, "var {:?}" , id) ,
499550 Arg ( id) =>
500- write ! ( fmt, "Arg( {:?}) " , id) ,
551+ write ! ( fmt, "arg {:?}" , id) ,
501552 Temp ( id) =>
502- write ! ( fmt, "Temp( {:?}) " , id) ,
553+ write ! ( fmt, "tmp {:?}" , id) ,
503554 Static ( id) =>
504555 write ! ( fmt, "Static({:?})" , id) ,
505556 ReturnPointer =>
506557 write ! ( fmt, "ReturnPointer" ) ,
507558 Projection ( ref data) =>
508559 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 ) ,
511562 ProjectionElem :: Deref =>
512563 write ! ( fmt, "(*{:?})" , data. base) ,
513564 ProjectionElem :: Field ( field) =>
@@ -671,12 +722,12 @@ impl<'tcx> Debug for Rvalue<'tcx> {
671722 Use ( ref lvalue) => write ! ( fmt, "{:?}" , lvalue) ,
672723 Repeat ( ref a, ref b) => write ! ( fmt, "[{:?}; {:?}]" , a, b) ,
673724 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) ,
677728 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) ,
680731 InlineAsm ( ref asm) => write ! ( fmt, "InlineAsm({:?})" , asm) ,
681732 Slice { ref input, from_start, from_end } =>
682733 write ! ( fmt, "{:?}[{:?}..-{:?}]" , input, from_start, from_end) ,
@@ -691,7 +742,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
691742// this does not necessarily mean that they are "==" in Rust -- in
692743// particular one must be wary of `NaN`!
693744
694- #[ derive( Clone , Debug , PartialEq , RustcEncodable , RustcDecodable ) ]
745+ #[ derive( Clone , PartialEq , RustcEncodable , RustcDecodable ) ]
695746pub struct Constant < ' tcx > {
696747 pub span : Span ,
697748 pub ty : Ty < ' tcx > ,
@@ -707,7 +758,7 @@ pub enum ItemKind {
707758 Method ,
708759}
709760
710- #[ derive( Clone , Debug , PartialEq , RustcEncodable , RustcDecodable ) ]
761+ #[ derive( Clone , PartialEq , RustcEncodable , RustcDecodable ) ]
711762pub enum Literal < ' tcx > {
712763 Item {
713764 def_id : DefId ,
@@ -718,3 +769,38 @@ pub enum Literal<'tcx> {
718769 value : ConstVal ,
719770 } ,
720771}
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