1
2
3
4
5 package ir
6
7 import (
8 "bytes"
9 "fmt"
10 "go/constant"
11 "io"
12 "os"
13 "path/filepath"
14 "reflect"
15 "strings"
16
17 "unicode/utf8"
18
19 "cmd/compile/internal/base"
20 "cmd/compile/internal/types"
21 "cmd/internal/src"
22 )
23
24
25
26 var OpNames = []string{
27 OADDR: "&",
28 OADD: "+",
29 OADDSTR: "+",
30 OANDAND: "&&",
31 OANDNOT: "&^",
32 OAND: "&",
33 OAPPEND: "append",
34 OAS: "=",
35 OAS2: "=",
36 OBREAK: "break",
37 OCALL: "function call",
38 OCAP: "cap",
39 OCASE: "case",
40 OCLEAR: "clear",
41 OCLOSE: "close",
42 OCOMPLEX: "complex",
43 OBITNOT: "^",
44 OCONTINUE: "continue",
45 OCOPY: "copy",
46 ODELETE: "delete",
47 ODEFER: "defer",
48 ODIV: "/",
49 OEQ: "==",
50 OFALL: "fallthrough",
51 OFOR: "for",
52 OGE: ">=",
53 OGOTO: "goto",
54 OGT: ">",
55 OIF: "if",
56 OIMAG: "imag",
57 OINLMARK: "inlmark",
58 ODEREF: "*",
59 OLEN: "len",
60 OLE: "<=",
61 OLSH: "<<",
62 OLT: "<",
63 OMAKE: "make",
64 ONEG: "-",
65 OMAX: "max",
66 OMIN: "min",
67 OMOD: "%",
68 OMUL: "*",
69 ONEW: "new",
70 ONE: "!=",
71 ONOT: "!",
72 OOROR: "||",
73 OOR: "|",
74 OPANIC: "panic",
75 OPLUS: "+",
76 OPRINTLN: "println",
77 OPRINT: "print",
78 ORANGE: "range",
79 OREAL: "real",
80 ORECV: "<-",
81 ORECOVER: "recover",
82 ORETURN: "return",
83 ORSH: ">>",
84 OSELECT: "select",
85 OSEND: "<-",
86 OSUB: "-",
87 OSWITCH: "switch",
88 OUNSAFEADD: "unsafe.Add",
89 OUNSAFESLICE: "unsafe.Slice",
90 OUNSAFESLICEDATA: "unsafe.SliceData",
91 OUNSAFESTRING: "unsafe.String",
92 OUNSAFESTRINGDATA: "unsafe.StringData",
93 OXOR: "^",
94 }
95
96
97 func (o Op) GoString() string {
98 if int(o) < len(OpNames) && OpNames[o] != "" {
99 return OpNames[o]
100 }
101 return o.String()
102 }
103
104
105
106
107
108
109 func (o Op) Format(s fmt.State, verb rune) {
110 switch verb {
111 default:
112 fmt.Fprintf(s, "%%!%c(Op=%d)", verb, int(o))
113 case 'v':
114 if s.Flag('+') {
115
116 io.WriteString(s, o.String())
117 return
118 }
119 io.WriteString(s, o.GoString())
120 }
121 }
122
123
124
125
126
127
128
129
130
131
132 func fmtNode(n Node, s fmt.State, verb rune) {
133
134
135 if s.Flag('+') && verb == 'v' {
136 dumpNode(s, n, 1)
137 return
138 }
139
140 if verb != 'v' && verb != 'S' && verb != 'L' {
141 fmt.Fprintf(s, "%%!%c(*Node=%p)", verb, n)
142 return
143 }
144
145 if n == nil {
146 fmt.Fprint(s, "<nil>")
147 return
148 }
149
150 t := n.Type()
151 if verb == 'L' && t != nil {
152 if t.Kind() == types.TNIL {
153 fmt.Fprint(s, "nil")
154 } else if n.Op() == ONAME && n.Name().AutoTemp() {
155 fmt.Fprintf(s, "%v value", t)
156 } else {
157 fmt.Fprintf(s, "%v (type %v)", n, t)
158 }
159 return
160 }
161
162
163
164 if OpPrec[n.Op()] < 0 {
165 stmtFmt(n, s)
166 return
167 }
168
169 exprFmt(n, s, 0)
170 }
171
172 var OpPrec = []int{
173 OAPPEND: 8,
174 OBYTES2STR: 8,
175 OARRAYLIT: 8,
176 OSLICELIT: 8,
177 ORUNES2STR: 8,
178 OCALLFUNC: 8,
179 OCALLINTER: 8,
180 OCALLMETH: 8,
181 OCALL: 8,
182 OCAP: 8,
183 OCLEAR: 8,
184 OCLOSE: 8,
185 OCOMPLIT: 8,
186 OCONVIFACE: 8,
187 OCONVNOP: 8,
188 OCONV: 8,
189 OCOPY: 8,
190 ODELETE: 8,
191 OGETG: 8,
192 OLEN: 8,
193 OLITERAL: 8,
194 OMAKESLICE: 8,
195 OMAKESLICECOPY: 8,
196 OMAKE: 8,
197 OMAPLIT: 8,
198 OMAX: 8,
199 OMIN: 8,
200 ONAME: 8,
201 ONEW: 8,
202 ONIL: 8,
203 ONONAME: 8,
204 OPANIC: 8,
205 OPAREN: 8,
206 OPRINTLN: 8,
207 OPRINT: 8,
208 ORUNESTR: 8,
209 OSLICE2ARR: 8,
210 OSLICE2ARRPTR: 8,
211 OSTR2BYTES: 8,
212 OSTR2RUNES: 8,
213 OSTRUCTLIT: 8,
214 OTYPE: 8,
215 OUNSAFEADD: 8,
216 OUNSAFESLICE: 8,
217 OUNSAFESLICEDATA: 8,
218 OUNSAFESTRING: 8,
219 OUNSAFESTRINGDATA: 8,
220 OINDEXMAP: 8,
221 OINDEX: 8,
222 OSLICE: 8,
223 OSLICESTR: 8,
224 OSLICEARR: 8,
225 OSLICE3: 8,
226 OSLICE3ARR: 8,
227 OSLICEHEADER: 8,
228 OSTRINGHEADER: 8,
229 ODOTINTER: 8,
230 ODOTMETH: 8,
231 ODOTPTR: 8,
232 ODOTTYPE2: 8,
233 ODOTTYPE: 8,
234 ODOT: 8,
235 OXDOT: 8,
236 OMETHVALUE: 8,
237 OMETHEXPR: 8,
238 OPLUS: 7,
239 ONOT: 7,
240 OBITNOT: 7,
241 ONEG: 7,
242 OADDR: 7,
243 ODEREF: 7,
244 ORECV: 7,
245 OMUL: 6,
246 ODIV: 6,
247 OMOD: 6,
248 OLSH: 6,
249 ORSH: 6,
250 OAND: 6,
251 OANDNOT: 6,
252 OADD: 5,
253 OSUB: 5,
254 OOR: 5,
255 OXOR: 5,
256 OEQ: 4,
257 OLT: 4,
258 OLE: 4,
259 OGE: 4,
260 OGT: 4,
261 ONE: 4,
262 OSEND: 3,
263 OANDAND: 2,
264 OOROR: 1,
265
266
267 OAS: -1,
268 OAS2: -1,
269 OAS2DOTTYPE: -1,
270 OAS2FUNC: -1,
271 OAS2MAPR: -1,
272 OAS2RECV: -1,
273 OASOP: -1,
274 OBLOCK: -1,
275 OBREAK: -1,
276 OCASE: -1,
277 OCONTINUE: -1,
278 ODCL: -1,
279 ODEFER: -1,
280 OFALL: -1,
281 OFOR: -1,
282 OGOTO: -1,
283 OIF: -1,
284 OLABEL: -1,
285 OGO: -1,
286 ORANGE: -1,
287 ORETURN: -1,
288 OSELECT: -1,
289 OSWITCH: -1,
290
291 OEND: 0,
292 }
293
294
295 func StmtWithInit(op Op) bool {
296 switch op {
297 case OIF, OFOR, OSWITCH:
298 return true
299 }
300 return false
301 }
302
303 func stmtFmt(n Node, s fmt.State) {
304
305
306
307
308
309
310 const exportFormat = false
311
312
313
314
315
316
317
318 simpleinit := len(n.Init()) == 1 && len(n.Init()[0].Init()) == 0 && StmtWithInit(n.Op())
319
320
321 complexinit := len(n.Init()) != 0 && !simpleinit && exportFormat
322
323
324 extrablock := complexinit && StmtWithInit(n.Op())
325
326 if extrablock {
327 fmt.Fprint(s, "{")
328 }
329
330 if complexinit {
331 fmt.Fprintf(s, " %v; ", n.Init())
332 }
333
334 switch n.Op() {
335 case ODCL:
336 n := n.(*Decl)
337 fmt.Fprintf(s, "var %v %v", n.X.Sym(), n.X.Type())
338
339
340
341
342 case OAS:
343 n := n.(*AssignStmt)
344 if n.Def && !complexinit {
345 fmt.Fprintf(s, "%v := %v", n.X, n.Y)
346 } else {
347 fmt.Fprintf(s, "%v = %v", n.X, n.Y)
348 }
349
350 case OASOP:
351 n := n.(*AssignOpStmt)
352 if n.IncDec {
353 if n.AsOp == OADD {
354 fmt.Fprintf(s, "%v++", n.X)
355 } else {
356 fmt.Fprintf(s, "%v--", n.X)
357 }
358 break
359 }
360
361 fmt.Fprintf(s, "%v %v= %v", n.X, n.AsOp, n.Y)
362
363 case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
364 n := n.(*AssignListStmt)
365 if n.Def && !complexinit {
366 fmt.Fprintf(s, "%.v := %.v", n.Lhs, n.Rhs)
367 } else {
368 fmt.Fprintf(s, "%.v = %.v", n.Lhs, n.Rhs)
369 }
370
371 case OBLOCK:
372 n := n.(*BlockStmt)
373 if len(n.List) != 0 {
374 fmt.Fprintf(s, "%v", n.List)
375 }
376
377 case ORETURN:
378 n := n.(*ReturnStmt)
379 fmt.Fprintf(s, "return %.v", n.Results)
380
381 case OTAILCALL:
382 n := n.(*TailCallStmt)
383 fmt.Fprintf(s, "tailcall %v", n.Call)
384
385 case OINLMARK:
386 n := n.(*InlineMarkStmt)
387 fmt.Fprintf(s, "inlmark %d", n.Index)
388
389 case OGO:
390 n := n.(*GoDeferStmt)
391 fmt.Fprintf(s, "go %v", n.Call)
392
393 case ODEFER:
394 n := n.(*GoDeferStmt)
395 fmt.Fprintf(s, "defer %v", n.Call)
396
397 case OIF:
398 n := n.(*IfStmt)
399 if simpleinit {
400 fmt.Fprintf(s, "if %v; %v { %v }", n.Init()[0], n.Cond, n.Body)
401 } else {
402 fmt.Fprintf(s, "if %v { %v }", n.Cond, n.Body)
403 }
404 if len(n.Else) != 0 {
405 fmt.Fprintf(s, " else { %v }", n.Else)
406 }
407
408 case OFOR:
409 n := n.(*ForStmt)
410 if !exportFormat {
411 fmt.Fprintf(s, "for loop")
412 break
413 }
414
415 fmt.Fprint(s, "for")
416 if n.DistinctVars {
417 fmt.Fprint(s, " /* distinct */")
418 }
419 if simpleinit {
420 fmt.Fprintf(s, " %v;", n.Init()[0])
421 } else if n.Post != nil {
422 fmt.Fprint(s, " ;")
423 }
424
425 if n.Cond != nil {
426 fmt.Fprintf(s, " %v", n.Cond)
427 }
428
429 if n.Post != nil {
430 fmt.Fprintf(s, "; %v", n.Post)
431 } else if simpleinit {
432 fmt.Fprint(s, ";")
433 }
434
435 fmt.Fprintf(s, " { %v }", n.Body)
436
437 case ORANGE:
438 n := n.(*RangeStmt)
439 if !exportFormat {
440 fmt.Fprint(s, "for loop")
441 break
442 }
443
444 fmt.Fprint(s, "for")
445 if n.Key != nil {
446 fmt.Fprintf(s, " %v", n.Key)
447 if n.Value != nil {
448 fmt.Fprintf(s, ", %v", n.Value)
449 }
450 fmt.Fprint(s, " =")
451 }
452 fmt.Fprintf(s, " range %v { %v }", n.X, n.Body)
453 if n.DistinctVars {
454 fmt.Fprint(s, " /* distinct vars */")
455 }
456
457 case OSELECT:
458 n := n.(*SelectStmt)
459 if !exportFormat {
460 fmt.Fprintf(s, "%v statement", n.Op())
461 break
462 }
463 fmt.Fprintf(s, "select { %v }", n.Cases)
464
465 case OSWITCH:
466 n := n.(*SwitchStmt)
467 if !exportFormat {
468 fmt.Fprintf(s, "%v statement", n.Op())
469 break
470 }
471 fmt.Fprintf(s, "switch")
472 if simpleinit {
473 fmt.Fprintf(s, " %v;", n.Init()[0])
474 }
475 if n.Tag != nil {
476 fmt.Fprintf(s, " %v ", n.Tag)
477 }
478 fmt.Fprintf(s, " { %v }", n.Cases)
479
480 case OCASE:
481 n := n.(*CaseClause)
482 if len(n.List) != 0 {
483 fmt.Fprintf(s, "case %.v", n.List)
484 } else {
485 fmt.Fprint(s, "default")
486 }
487 fmt.Fprintf(s, ": %v", n.Body)
488
489 case OBREAK, OCONTINUE, OGOTO, OFALL:
490 n := n.(*BranchStmt)
491 if n.Label != nil {
492 fmt.Fprintf(s, "%v %v", n.Op(), n.Label)
493 } else {
494 fmt.Fprintf(s, "%v", n.Op())
495 }
496
497 case OLABEL:
498 n := n.(*LabelStmt)
499 fmt.Fprintf(s, "%v: ", n.Label)
500 }
501
502 if extrablock {
503 fmt.Fprint(s, "}")
504 }
505 }
506
507 func exprFmt(n Node, s fmt.State, prec int) {
508
509
510
511
512
513
514 const exportFormat = false
515
516 for {
517 if n == nil {
518 fmt.Fprint(s, "<nil>")
519 return
520 }
521
522
523 switch nn := n; nn.Op() {
524 case OADDR:
525 nn := nn.(*AddrExpr)
526 if nn.Implicit() {
527 n = nn.X
528 continue
529 }
530 case ODEREF:
531 nn := nn.(*StarExpr)
532 if nn.Implicit() {
533 n = nn.X
534 continue
535 }
536 case OCONV, OCONVNOP, OCONVIFACE:
537 nn := nn.(*ConvExpr)
538 if nn.Implicit() {
539 n = nn.X
540 continue
541 }
542 }
543
544 break
545 }
546
547 nprec := OpPrec[n.Op()]
548 if n.Op() == OTYPE && n.Type() != nil && n.Type().IsPtr() {
549 nprec = OpPrec[ODEREF]
550 }
551
552 if prec > nprec {
553 fmt.Fprintf(s, "(%v)", n)
554 return
555 }
556
557 switch n.Op() {
558 case OPAREN:
559 n := n.(*ParenExpr)
560 fmt.Fprintf(s, "(%v)", n.X)
561
562 case ONIL:
563 fmt.Fprint(s, "nil")
564
565 case OLITERAL:
566 if n.Sym() != nil {
567 fmt.Fprint(s, n.Sym())
568 return
569 }
570
571 typ := n.Type()
572 val := n.Val()
573
574
575 if typ == types.RuneType || typ == types.UntypedRune {
576 if x, ok := constant.Uint64Val(val); ok && x <= utf8.MaxRune {
577 fmt.Fprintf(s, "%q", x)
578 return
579 }
580 }
581
582
583
584 if k := val.Kind(); typ == types.Types[types.DefaultKinds[k]] || typ == types.UntypedTypes[k] {
585 fmt.Fprint(s, val)
586 } else {
587 fmt.Fprintf(s, "%v(%v)", typ, val)
588 }
589
590 case ODCLFUNC:
591 n := n.(*Func)
592 if sym := n.Sym(); sym != nil {
593 fmt.Fprint(s, sym)
594 return
595 }
596 fmt.Fprintf(s, "<unnamed Func>")
597
598 case ONAME:
599 n := n.(*Name)
600
601
602 if !exportFormat && n.Sym() != nil && n.Sym().Name[0] == '~' && n.Sym().Name[1] == 'b' {
603 fmt.Fprint(s, "_")
604 return
605 }
606 fallthrough
607 case ONONAME:
608 fmt.Fprint(s, n.Sym())
609
610 case OLINKSYMOFFSET:
611 n := n.(*LinksymOffsetExpr)
612 fmt.Fprintf(s, "(%v)(%s@%d)", n.Type(), n.Linksym.Name, n.Offset_)
613
614 case OTYPE:
615 if n.Type() == nil && n.Sym() != nil {
616 fmt.Fprint(s, n.Sym())
617 return
618 }
619 fmt.Fprintf(s, "%v", n.Type())
620
621 case OCLOSURE:
622 n := n.(*ClosureExpr)
623 if !exportFormat {
624 fmt.Fprint(s, "func literal")
625 return
626 }
627 fmt.Fprintf(s, "%v { %v }", n.Type(), n.Func.Body)
628
629 case OPTRLIT:
630 n := n.(*AddrExpr)
631 fmt.Fprintf(s, "&%v", n.X)
632
633 case OCOMPLIT, OSTRUCTLIT, OARRAYLIT, OSLICELIT, OMAPLIT:
634 n := n.(*CompLitExpr)
635 if n.Implicit() {
636 fmt.Fprintf(s, "... argument")
637 return
638 }
639 fmt.Fprintf(s, "%v{%s}", n.Type(), ellipsisIf(len(n.List) != 0))
640
641 case OKEY:
642 n := n.(*KeyExpr)
643 if n.Key != nil && n.Value != nil {
644 fmt.Fprintf(s, "%v:%v", n.Key, n.Value)
645 return
646 }
647
648 if n.Key == nil && n.Value != nil {
649 fmt.Fprintf(s, ":%v", n.Value)
650 return
651 }
652 if n.Key != nil && n.Value == nil {
653 fmt.Fprintf(s, "%v:", n.Key)
654 return
655 }
656 fmt.Fprint(s, ":")
657
658 case OSTRUCTKEY:
659 n := n.(*StructKeyExpr)
660 fmt.Fprintf(s, "%v:%v", n.Field, n.Value)
661
662 case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH, OMETHVALUE, OMETHEXPR:
663 n := n.(*SelectorExpr)
664 exprFmt(n.X, s, nprec)
665 if n.Sel == nil {
666 fmt.Fprint(s, ".<nil>")
667 return
668 }
669 fmt.Fprintf(s, ".%s", n.Sel.Name)
670
671 case ODOTTYPE, ODOTTYPE2:
672 n := n.(*TypeAssertExpr)
673 exprFmt(n.X, s, nprec)
674 fmt.Fprintf(s, ".(%v)", n.Type())
675
676 case OINDEX, OINDEXMAP:
677 n := n.(*IndexExpr)
678 exprFmt(n.X, s, nprec)
679 fmt.Fprintf(s, "[%v]", n.Index)
680
681 case OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR:
682 n := n.(*SliceExpr)
683 exprFmt(n.X, s, nprec)
684 fmt.Fprint(s, "[")
685 if n.Low != nil {
686 fmt.Fprint(s, n.Low)
687 }
688 fmt.Fprint(s, ":")
689 if n.High != nil {
690 fmt.Fprint(s, n.High)
691 }
692 if n.Op().IsSlice3() {
693 fmt.Fprint(s, ":")
694 if n.Max != nil {
695 fmt.Fprint(s, n.Max)
696 }
697 }
698 fmt.Fprint(s, "]")
699
700 case OSLICEHEADER:
701 n := n.(*SliceHeaderExpr)
702 fmt.Fprintf(s, "sliceheader{%v,%v,%v}", n.Ptr, n.Len, n.Cap)
703
704 case OCOMPLEX, OCOPY, OUNSAFEADD, OUNSAFESLICE:
705 n := n.(*BinaryExpr)
706 fmt.Fprintf(s, "%v(%v, %v)", n.Op(), n.X, n.Y)
707
708 case OCONV,
709 OCONVIFACE,
710 OCONVNOP,
711 OBYTES2STR,
712 ORUNES2STR,
713 OSTR2BYTES,
714 OSTR2RUNES,
715 ORUNESTR,
716 OSLICE2ARR,
717 OSLICE2ARRPTR:
718 n := n.(*ConvExpr)
719 if n.Type() == nil || n.Type().Sym() == nil {
720 fmt.Fprintf(s, "(%v)", n.Type())
721 } else {
722 fmt.Fprintf(s, "%v", n.Type())
723 }
724 fmt.Fprintf(s, "(%v)", n.X)
725
726 case OREAL,
727 OIMAG,
728 OCAP,
729 OCLEAR,
730 OCLOSE,
731 OLEN,
732 ONEW,
733 OPANIC:
734 n := n.(*UnaryExpr)
735 fmt.Fprintf(s, "%v(%v)", n.Op(), n.X)
736
737 case OAPPEND,
738 ODELETE,
739 OMAKE,
740 OMAX,
741 OMIN,
742 ORECOVER,
743 OPRINT,
744 OPRINTLN:
745 n := n.(*CallExpr)
746 if n.IsDDD {
747 fmt.Fprintf(s, "%v(%.v...)", n.Op(), n.Args)
748 return
749 }
750 fmt.Fprintf(s, "%v(%.v)", n.Op(), n.Args)
751
752 case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, OGETG:
753 n := n.(*CallExpr)
754 exprFmt(n.Fun, s, nprec)
755 if n.IsDDD {
756 fmt.Fprintf(s, "(%.v...)", n.Args)
757 return
758 }
759 fmt.Fprintf(s, "(%.v)", n.Args)
760
761 case OINLCALL:
762 n := n.(*InlinedCallExpr)
763
764 if len(n.ReturnVars) == 1 {
765 fmt.Fprintf(s, "%v", n.ReturnVars[0])
766 return
767 }
768 fmt.Fprintf(s, "(.%v)", n.ReturnVars)
769
770 case OMAKEMAP, OMAKECHAN, OMAKESLICE:
771 n := n.(*MakeExpr)
772 if n.Cap != nil {
773 fmt.Fprintf(s, "make(%v, %v, %v)", n.Type(), n.Len, n.Cap)
774 return
775 }
776 if n.Len != nil && (n.Op() == OMAKESLICE || !n.Len.Type().IsUntyped()) {
777 fmt.Fprintf(s, "make(%v, %v)", n.Type(), n.Len)
778 return
779 }
780 fmt.Fprintf(s, "make(%v)", n.Type())
781
782 case OMAKESLICECOPY:
783 n := n.(*MakeExpr)
784 fmt.Fprintf(s, "makeslicecopy(%v, %v, %v)", n.Type(), n.Len, n.Cap)
785
786 case OPLUS, ONEG, OBITNOT, ONOT, ORECV:
787
788 n := n.(*UnaryExpr)
789 fmt.Fprintf(s, "%v", n.Op())
790 if n.X != nil && n.X.Op() == n.Op() {
791 fmt.Fprint(s, " ")
792 }
793 exprFmt(n.X, s, nprec+1)
794
795 case OADDR:
796 n := n.(*AddrExpr)
797 fmt.Fprintf(s, "%v", n.Op())
798 if n.X != nil && n.X.Op() == n.Op() {
799 fmt.Fprint(s, " ")
800 }
801 exprFmt(n.X, s, nprec+1)
802
803 case ODEREF:
804 n := n.(*StarExpr)
805 fmt.Fprintf(s, "%v", n.Op())
806 exprFmt(n.X, s, nprec+1)
807
808
809 case OADD,
810 OAND,
811 OANDNOT,
812 ODIV,
813 OEQ,
814 OGE,
815 OGT,
816 OLE,
817 OLT,
818 OLSH,
819 OMOD,
820 OMUL,
821 ONE,
822 OOR,
823 ORSH,
824 OSUB,
825 OXOR:
826 n := n.(*BinaryExpr)
827 exprFmt(n.X, s, nprec)
828 fmt.Fprintf(s, " %v ", n.Op())
829 exprFmt(n.Y, s, nprec+1)
830
831 case OANDAND,
832 OOROR:
833 n := n.(*LogicalExpr)
834 exprFmt(n.X, s, nprec)
835 fmt.Fprintf(s, " %v ", n.Op())
836 exprFmt(n.Y, s, nprec+1)
837
838 case OSEND:
839 n := n.(*SendStmt)
840 exprFmt(n.Chan, s, nprec)
841 fmt.Fprintf(s, " <- ")
842 exprFmt(n.Value, s, nprec+1)
843
844 case OADDSTR:
845 n := n.(*AddStringExpr)
846 for i, n1 := range n.List {
847 if i != 0 {
848 fmt.Fprint(s, " + ")
849 }
850 exprFmt(n1, s, nprec)
851 }
852 default:
853 fmt.Fprintf(s, "<node %v>", n.Op())
854 }
855 }
856
857 func ellipsisIf(b bool) string {
858 if b {
859 return "..."
860 }
861 return ""
862 }
863
864
865
866
867
868
869
870
871
872 func (l Nodes) Format(s fmt.State, verb rune) {
873 if s.Flag('+') && verb == 'v' {
874
875 dumpNodes(s, l, 1)
876 return
877 }
878
879 if verb != 'v' {
880 fmt.Fprintf(s, "%%!%c(Nodes)", verb)
881 return
882 }
883
884 sep := "; "
885 if _, ok := s.Precision(); ok {
886 sep = ", "
887 }
888
889 for i, n := range l {
890 fmt.Fprint(s, n)
891 if i+1 < len(l) {
892 fmt.Fprint(s, sep)
893 }
894 }
895 }
896
897
898
899
900 func Dump(s string, n Node) {
901 fmt.Printf("%s%+v\n", s, n)
902 }
903
904
905 func DumpList(s string, list Nodes) {
906 var buf bytes.Buffer
907 FDumpList(&buf, s, list)
908 os.Stdout.Write(buf.Bytes())
909 }
910
911
912 func FDumpList(w io.Writer, s string, list Nodes) {
913 io.WriteString(w, s)
914 dumpNodes(w, list, 1)
915 io.WriteString(w, "\n")
916 }
917
918
919 func indent(w io.Writer, depth int) {
920 fmt.Fprint(w, "\n")
921 for i := 0; i < depth; i++ {
922 fmt.Fprint(w, ". ")
923 }
924 }
925
926
927 var EscFmt func(n Node) string
928
929
930 func dumpNodeHeader(w io.Writer, n Node) {
931
932 if base.Debug.DumpPtrs != 0 {
933 fmt.Fprintf(w, " p(%p)", n)
934 }
935
936 if base.Debug.DumpPtrs != 0 && n.Name() != nil && n.Name().Defn != nil {
937
938 fmt.Fprintf(w, " defn(%p)", n.Name().Defn)
939 }
940
941 if base.Debug.DumpPtrs != 0 && n.Name() != nil && n.Name().Curfn != nil {
942
943 fmt.Fprintf(w, " curfn(%p)", n.Name().Curfn)
944 }
945 if base.Debug.DumpPtrs != 0 && n.Name() != nil && n.Name().Outer != nil {
946
947 fmt.Fprintf(w, " outer(%p)", n.Name().Outer)
948 }
949
950 if EscFmt != nil {
951 if esc := EscFmt(n); esc != "" {
952 fmt.Fprintf(w, " %s", esc)
953 }
954 }
955
956 if n.Sym() != nil && n.Op() != ONAME && n.Op() != ONONAME && n.Op() != OTYPE {
957 fmt.Fprintf(w, " %+v", n.Sym())
958 }
959
960
961 v := reflect.ValueOf(n).Elem()
962 t := v.Type()
963 nf := t.NumField()
964 for i := 0; i < nf; i++ {
965 tf := t.Field(i)
966 if tf.PkgPath != "" {
967
968 continue
969 }
970 k := tf.Type.Kind()
971 if reflect.Bool <= k && k <= reflect.Complex128 {
972 name := strings.TrimSuffix(tf.Name, "_")
973 vf := v.Field(i)
974 vfi := vf.Interface()
975 if name == "Offset" && vfi == types.BADWIDTH || name != "Offset" && vf.IsZero() {
976 continue
977 }
978 if vfi == true {
979 fmt.Fprintf(w, " %s", name)
980 } else {
981 fmt.Fprintf(w, " %s:%+v", name, vf.Interface())
982 }
983 }
984 }
985
986
987
988 v = reflect.ValueOf(n)
989 t = v.Type()
990 nm := t.NumMethod()
991 for i := 0; i < nm; i++ {
992 tm := t.Method(i)
993 if tm.PkgPath != "" {
994
995 continue
996 }
997 m := v.Method(i)
998 mt := m.Type()
999 if mt.NumIn() == 0 && mt.NumOut() == 1 && mt.Out(0).Kind() == reflect.Bool {
1000
1001
1002
1003
1004 func() {
1005 defer func() { recover() }()
1006 if m.Call(nil)[0].Bool() {
1007 name := strings.TrimSuffix(tm.Name, "_")
1008 fmt.Fprintf(w, " %s", name)
1009 }
1010 }()
1011 }
1012 }
1013
1014 if n.Op() == OCLOSURE {
1015 n := n.(*ClosureExpr)
1016 if fn := n.Func; fn != nil && fn.Nname.Sym() != nil {
1017 fmt.Fprintf(w, " fnName(%+v)", fn.Nname.Sym())
1018 }
1019 }
1020
1021 if n.Type() != nil {
1022 if n.Op() == OTYPE {
1023 fmt.Fprintf(w, " type")
1024 }
1025 fmt.Fprintf(w, " %+v", n.Type())
1026 }
1027 if n.Typecheck() != 0 {
1028 fmt.Fprintf(w, " tc(%d)", n.Typecheck())
1029 }
1030
1031 if n.Pos().IsKnown() {
1032 fmt.Fprint(w, " # ")
1033 switch n.Pos().IsStmt() {
1034 case src.PosNotStmt:
1035 fmt.Fprint(w, "_")
1036 case src.PosIsStmt:
1037 fmt.Fprint(w, "+")
1038 }
1039 sep := ""
1040 base.Ctxt.AllPos(n.Pos(), func(pos src.Pos) {
1041 fmt.Fprint(w, sep)
1042 sep = " "
1043
1044 file := filepath.Base(pos.Filename())
1045
1046 fmt.Fprintf(w, "%s:%d:%d", file, pos.Line(), pos.Col())
1047 })
1048 }
1049 }
1050
1051 func dumpNode(w io.Writer, n Node, depth int) {
1052 indent(w, depth)
1053 if depth > 40 {
1054 fmt.Fprint(w, "...")
1055 return
1056 }
1057
1058 if n == nil {
1059 fmt.Fprint(w, "NilIrNode")
1060 return
1061 }
1062
1063 if len(n.Init()) != 0 {
1064 fmt.Fprintf(w, "%+v-init", n.Op())
1065 dumpNodes(w, n.Init(), depth+1)
1066 indent(w, depth)
1067 }
1068
1069 switch n.Op() {
1070 default:
1071 fmt.Fprintf(w, "%+v", n.Op())
1072 dumpNodeHeader(w, n)
1073
1074 case OLITERAL:
1075 fmt.Fprintf(w, "%+v-%v", n.Op(), n.Val())
1076 dumpNodeHeader(w, n)
1077 return
1078
1079 case ONAME, ONONAME:
1080 if n.Sym() != nil {
1081 fmt.Fprintf(w, "%+v-%+v", n.Op(), n.Sym())
1082 } else {
1083 fmt.Fprintf(w, "%+v", n.Op())
1084 }
1085 dumpNodeHeader(w, n)
1086 return
1087
1088 case OLINKSYMOFFSET:
1089 n := n.(*LinksymOffsetExpr)
1090 fmt.Fprintf(w, "%+v-%v", n.Op(), n.Linksym)
1091
1092 if n.Offset_ != 0 {
1093 fmt.Fprintf(w, "%+v", n.Offset_)
1094 }
1095 dumpNodeHeader(w, n)
1096
1097 case OASOP:
1098 n := n.(*AssignOpStmt)
1099 fmt.Fprintf(w, "%+v-%+v", n.Op(), n.AsOp)
1100 dumpNodeHeader(w, n)
1101
1102 case OTYPE:
1103 fmt.Fprintf(w, "%+v %+v", n.Op(), n.Sym())
1104 dumpNodeHeader(w, n)
1105 return
1106
1107 case OCLOSURE:
1108 fmt.Fprintf(w, "%+v", n.Op())
1109 dumpNodeHeader(w, n)
1110
1111 case ODCLFUNC:
1112
1113
1114 n := n.(*Func)
1115 fmt.Fprintf(w, "%+v", n.Op())
1116 dumpNodeHeader(w, n)
1117 fn := n
1118 if len(fn.Dcl) > 0 {
1119 indent(w, depth)
1120 fmt.Fprintf(w, "%+v-Dcl", n.Op())
1121 for _, dcl := range n.Dcl {
1122 dumpNode(w, dcl, depth+1)
1123 }
1124 }
1125 if len(fn.ClosureVars) > 0 {
1126 indent(w, depth)
1127 fmt.Fprintf(w, "%+v-ClosureVars", n.Op())
1128 for _, cv := range fn.ClosureVars {
1129 dumpNode(w, cv, depth+1)
1130 }
1131 }
1132 if len(fn.Body) > 0 {
1133 indent(w, depth)
1134 fmt.Fprintf(w, "%+v-body", n.Op())
1135 dumpNodes(w, fn.Body, depth+1)
1136 }
1137 return
1138 }
1139
1140 v := reflect.ValueOf(n).Elem()
1141 t := reflect.TypeOf(n).Elem()
1142 nf := t.NumField()
1143 for i := 0; i < nf; i++ {
1144 tf := t.Field(i)
1145 vf := v.Field(i)
1146 if tf.PkgPath != "" {
1147
1148 continue
1149 }
1150 switch tf.Type.Kind() {
1151 case reflect.Interface, reflect.Ptr, reflect.Slice:
1152 if vf.IsNil() {
1153 continue
1154 }
1155 }
1156 name := strings.TrimSuffix(tf.Name, "_")
1157
1158
1159
1160 switch name {
1161 case "X", "Y", "Index", "Chan", "Value", "Call":
1162 name = ""
1163 }
1164 switch val := vf.Interface().(type) {
1165 case Node:
1166 if name != "" {
1167 indent(w, depth)
1168 fmt.Fprintf(w, "%+v-%s", n.Op(), name)
1169 }
1170 dumpNode(w, val, depth+1)
1171 case Nodes:
1172 if len(val) == 0 {
1173 continue
1174 }
1175 if name != "" {
1176 indent(w, depth)
1177 fmt.Fprintf(w, "%+v-%s", n.Op(), name)
1178 }
1179 dumpNodes(w, val, depth+1)
1180 default:
1181 if vf.Kind() == reflect.Slice && vf.Type().Elem().Implements(nodeType) {
1182 if vf.Len() == 0 {
1183 continue
1184 }
1185 if name != "" {
1186 indent(w, depth)
1187 fmt.Fprintf(w, "%+v-%s", n.Op(), name)
1188 }
1189 for i, n := 0, vf.Len(); i < n; i++ {
1190 dumpNode(w, vf.Index(i).Interface().(Node), depth+1)
1191 }
1192 }
1193 }
1194 }
1195 }
1196
1197 var nodeType = reflect.TypeOf((*Node)(nil)).Elem()
1198
1199 func dumpNodes(w io.Writer, list Nodes, depth int) {
1200 if len(list) == 0 {
1201 fmt.Fprintf(w, " <nil>")
1202 return
1203 }
1204
1205 for _, n := range list {
1206 dumpNode(w, n, depth)
1207 }
1208 }
1209
View as plain text