Source file src/pkg/cmd/compile/internal/gc/dump.go
     1	
     2	
     3	
     4	
     5	
     6	
     7	
     8	
     9	package gc
    10	
    11	import (
    12		"cmd/compile/internal/types"
    13		"cmd/internal/src"
    14		"fmt"
    15		"io"
    16		"os"
    17		"reflect"
    18		"regexp"
    19	)
    20	
    21	
    22	func dump(root interface{}, filter string, depth int) {
    23		fdump(os.Stderr, root, filter, depth)
    24	}
    25	
    26	
    27	
    28	
    29	
    30	
    31	
    32	
    33	
    34	
    35	
    36	
    37	
    38	
    39	
    40	
    41	
    42	
    43	func fdump(w io.Writer, root interface{}, filter string, depth int) {
    44		if root == nil {
    45			fmt.Fprintln(w, "nil")
    46			return
    47		}
    48	
    49		if filter == "" {
    50			filter = ".*" 
    51		}
    52	
    53		p := dumper{
    54			output:  w,
    55			fieldrx: regexp.MustCompile(filter),
    56			ptrmap:  make(map[uintptr]int),
    57			last:    '\n', 
    58		}
    59	
    60		p.dump(reflect.ValueOf(root), depth)
    61		p.printf("\n")
    62	}
    63	
    64	type dumper struct {
    65		output  io.Writer
    66		fieldrx *regexp.Regexp  
    67		ptrmap  map[uintptr]int 
    68		lastadr string          
    69	
    70		
    71		indent int  
    72		last   byte 
    73		line   int  
    74	}
    75	
    76	var indentBytes = []byte(".  ")
    77	
    78	func (p *dumper) Write(data []byte) (n int, err error) {
    79		var m int
    80		for i, b := range data {
    81			
    82			if b == '\n' {
    83				m, err = p.output.Write(data[n : i+1])
    84				n += m
    85				if err != nil {
    86					return
    87				}
    88			} else if p.last == '\n' {
    89				p.line++
    90				_, err = fmt.Fprintf(p.output, "%6d  ", p.line)
    91				if err != nil {
    92					return
    93				}
    94				for j := p.indent; j > 0; j-- {
    95					_, err = p.output.Write(indentBytes)
    96					if err != nil {
    97						return
    98					}
    99				}
   100			}
   101			p.last = b
   102		}
   103		if len(data) > n {
   104			m, err = p.output.Write(data[n:])
   105			n += m
   106		}
   107		return
   108	}
   109	
   110	
   111	func (p *dumper) printf(format string, args ...interface{}) {
   112		if _, err := fmt.Fprintf(p, format, args...); err != nil {
   113			panic(err)
   114		}
   115	}
   116	
   117	
   118	
   119	
   120	
   121	func (p *dumper) addr(x reflect.Value) string {
   122		if !x.CanAddr() {
   123			return "?"
   124		}
   125		adr := fmt.Sprintf("%p", x.Addr().Interface())
   126		s := adr
   127		if i := commonPrefixLen(p.lastadr, adr); i > 0 {
   128			s = "0x…" + adr[i:]
   129		}
   130		p.lastadr = adr
   131		return s
   132	}
   133	
   134	
   135	func (p *dumper) dump(x reflect.Value, depth int) {
   136		if depth == 0 {
   137			p.printf("…")
   138			return
   139		}
   140	
   141		
   142		switch v := x.Interface().(type) {
   143		case Nodes:
   144			
   145			
   146			x = reflect.ValueOf(v.Slice())
   147	
   148		case src.XPos:
   149			p.printf("%s", linestr(v))
   150			return
   151	
   152		case *types.Node:
   153			x = reflect.ValueOf(asNode(v))
   154		}
   155	
   156		switch x.Kind() {
   157		case reflect.String:
   158			p.printf("%q", x.Interface()) 
   159	
   160		case reflect.Interface:
   161			if x.IsNil() {
   162				p.printf("nil")
   163				return
   164			}
   165			p.dump(x.Elem(), depth-1)
   166	
   167		case reflect.Ptr:
   168			if x.IsNil() {
   169				p.printf("nil")
   170				return
   171			}
   172	
   173			p.printf("*")
   174			ptr := x.Pointer()
   175			if line, exists := p.ptrmap[ptr]; exists {
   176				p.printf("(@%d)", line)
   177				return
   178			}
   179			p.ptrmap[ptr] = p.line
   180			p.dump(x.Elem(), depth) 
   181	
   182		case reflect.Slice:
   183			if x.IsNil() {
   184				p.printf("nil")
   185				return
   186			}
   187			p.printf("%s (%d entries) {", x.Type(), x.Len())
   188			if x.Len() > 0 {
   189				p.indent++
   190				p.printf("\n")
   191				for i, n := 0, x.Len(); i < n; i++ {
   192					p.printf("%d: ", i)
   193					p.dump(x.Index(i), depth-1)
   194					p.printf("\n")
   195				}
   196				p.indent--
   197			}
   198			p.printf("}")
   199	
   200		case reflect.Struct:
   201			typ := x.Type()
   202	
   203			isNode := false
   204			if n, ok := x.Interface().(Node); ok {
   205				isNode = true
   206				p.printf("%s %s {", n.Op.String(), p.addr(x))
   207			} else {
   208				p.printf("%s {", typ)
   209			}
   210			p.indent++
   211	
   212			first := true
   213			omitted := false
   214			for i, n := 0, typ.NumField(); i < n; i++ {
   215				
   216				
   217				if name := typ.Field(i).Name; types.IsExported(name) {
   218					if !p.fieldrx.MatchString(name) {
   219						omitted = true
   220						continue 
   221					}
   222	
   223					
   224					if isNode && name == "Op" {
   225						omitted = true
   226						continue 
   227					}
   228					x := x.Field(i)
   229					if isZeroVal(x) {
   230						omitted = true
   231						continue 
   232					}
   233					if n, ok := x.Interface().(Nodes); ok && n.Len() == 0 {
   234						omitted = true
   235						continue 
   236					}
   237	
   238					if first {
   239						p.printf("\n")
   240						first = false
   241					}
   242					p.printf("%s: ", name)
   243					p.dump(x, depth-1)
   244					p.printf("\n")
   245				}
   246			}
   247			if omitted {
   248				p.printf("…\n")
   249			}
   250	
   251			p.indent--
   252			p.printf("}")
   253	
   254		default:
   255			p.printf("%v", x.Interface())
   256		}
   257	}
   258	
   259	func isZeroVal(x reflect.Value) bool {
   260		switch x.Kind() {
   261		case reflect.Bool:
   262			return !x.Bool()
   263		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   264			return x.Int() == 0
   265		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   266			return x.Uint() == 0
   267		case reflect.String:
   268			return x.String() == ""
   269		case reflect.Interface, reflect.Ptr, reflect.Slice:
   270			return x.IsNil()
   271		}
   272		return false
   273	}
   274	
   275	func commonPrefixLen(a, b string) (i int) {
   276		for i < len(a) && i < len(b) && a[i] == b[i] {
   277			i++
   278		}
   279		return
   280	}
   281	
View as plain text