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