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", rune(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
901 func Dump(s string, n Node) {
902 fmt.Printf("%s%+v\n", s, n)
903 }
904
905
906
907 func FDump(w io.Writer, s string, n Node) {
908 fmt.Fprintf(w, "%s%+v\n", s, n)
909 }
910
911
912
913 func DumpList(s string, list Nodes) {
914 var buf bytes.Buffer
915 FDumpList(&buf, s, list)
916 os.Stdout.Write(buf.Bytes())
917 }
918
919
920
921 func FDumpList(w io.Writer, s string, list Nodes) {
922 io.WriteString(w, s)
923 dumpNodes(w, list, 1)
924 io.WriteString(w, "\n")
925 }
926
927
928 func indent(w io.Writer, depth int) {
929 fmt.Fprint(w, "\n")
930 for i := 0; i < depth; i++ {
931 fmt.Fprint(w, ". ")
932 }
933 }
934
935
936 var EscFmt func(n Node) string
937
938
939 func dumpNodeHeader(w io.Writer, n Node) {
940
941 if base.Debug.DumpPtrs != 0 {
942 fmt.Fprintf(w, " p(%p)", n)
943 }
944
945 if base.Debug.DumpPtrs != 0 && n.Name() != nil && n.Name().Defn != nil {
946
947 fmt.Fprintf(w, " defn(%p)", n.Name().Defn)
948 }
949
950 if base.Debug.DumpPtrs != 0 && n.Name() != nil && n.Name().Curfn != nil {
951
952 fmt.Fprintf(w, " curfn(%p)", n.Name().Curfn)
953 }
954 if base.Debug.DumpPtrs != 0 && n.Name() != nil && n.Name().Outer != nil {
955
956 fmt.Fprintf(w, " outer(%p)", n.Name().Outer)
957 }
958
959 if EscFmt != nil {
960 if esc := EscFmt(n); esc != "" {
961 fmt.Fprintf(w, " %s", esc)
962 }
963 }
964
965 if n.Sym() != nil && n.Op() != ONAME && n.Op() != ONONAME && n.Op() != OTYPE {
966 fmt.Fprintf(w, " %+v", n.Sym())
967 }
968
969
970 v := reflect.ValueOf(n).Elem()
971 t := v.Type()
972 nf := t.NumField()
973 for i := 0; i < nf; i++ {
974 tf := t.Field(i)
975 if tf.PkgPath != "" {
976
977 continue
978 }
979 k := tf.Type.Kind()
980 if reflect.Bool <= k && k <= reflect.Complex128 {
981 name := strings.TrimSuffix(tf.Name, "_")
982 vf := v.Field(i)
983 vfi := vf.Interface()
984 if name == "Offset" && vfi == types.BADWIDTH || name != "Offset" && vf.IsZero() {
985 continue
986 }
987 if vfi == true {
988 fmt.Fprintf(w, " %s", name)
989 } else {
990 fmt.Fprintf(w, " %s:%+v", name, vf.Interface())
991 }
992 }
993 }
994
995
996
997 v = reflect.ValueOf(n)
998 t = v.Type()
999 nm := t.NumMethod()
1000 for i := 0; i < nm; i++ {
1001 tm := t.Method(i)
1002 if tm.PkgPath != "" {
1003
1004 continue
1005 }
1006 m := v.Method(i)
1007 mt := m.Type()
1008 if mt.NumIn() == 0 && mt.NumOut() == 1 && mt.Out(0).Kind() == reflect.Bool {
1009
1010
1011
1012
1013 func() {
1014 defer func() { recover() }()
1015 if m.Call(nil)[0].Bool() {
1016 name := strings.TrimSuffix(tm.Name, "_")
1017 fmt.Fprintf(w, " %s", name)
1018 }
1019 }()
1020 }
1021 }
1022
1023 if n.Op() == OCLOSURE {
1024 n := n.(*ClosureExpr)
1025 if fn := n.Func; fn != nil && fn.Nname.Sym() != nil {
1026 fmt.Fprintf(w, " fnName(%+v)", fn.Nname.Sym())
1027 }
1028 }
1029
1030 if n.Type() != nil {
1031 if n.Op() == OTYPE {
1032 fmt.Fprintf(w, " type")
1033 }
1034 fmt.Fprintf(w, " %+v", n.Type())
1035 }
1036 if n.Typecheck() != 0 {
1037 fmt.Fprintf(w, " tc(%d)", n.Typecheck())
1038 }
1039
1040 if n.Pos().IsKnown() {
1041 fmt.Fprint(w, " # ")
1042 switch n.Pos().IsStmt() {
1043 case src.PosNotStmt:
1044 fmt.Fprint(w, "_")
1045 case src.PosIsStmt:
1046 fmt.Fprint(w, "+")
1047 }
1048 sep := ""
1049 base.Ctxt.AllPos(n.Pos(), func(pos src.Pos) {
1050 fmt.Fprint(w, sep)
1051 sep = " "
1052
1053 file := filepath.Base(pos.Filename())
1054
1055 fmt.Fprintf(w, "%s:%d:%d", file, pos.Line(), pos.Col())
1056 })
1057 }
1058 }
1059
1060 func dumpNode(w io.Writer, n Node, depth int) {
1061 indent(w, depth)
1062 if depth > 40 {
1063 fmt.Fprint(w, "...")
1064 return
1065 }
1066
1067 if n == nil {
1068 fmt.Fprint(w, "NilIrNode")
1069 return
1070 }
1071
1072 if len(n.Init()) != 0 {
1073 fmt.Fprintf(w, "%+v-init", n.Op())
1074 dumpNodes(w, n.Init(), depth+1)
1075 indent(w, depth)
1076 }
1077
1078 switch n.Op() {
1079 default:
1080 fmt.Fprintf(w, "%+v", n.Op())
1081 dumpNodeHeader(w, n)
1082
1083 case OLITERAL:
1084 fmt.Fprintf(w, "%+v-%v", n.Op(), n.Val())
1085 dumpNodeHeader(w, n)
1086 return
1087
1088 case ONAME, ONONAME:
1089 if n.Sym() != nil {
1090 fmt.Fprintf(w, "%+v-%+v", n.Op(), n.Sym())
1091 } else {
1092 fmt.Fprintf(w, "%+v", n.Op())
1093 }
1094 dumpNodeHeader(w, n)
1095 return
1096
1097 case OLINKSYMOFFSET:
1098 n := n.(*LinksymOffsetExpr)
1099 fmt.Fprintf(w, "%+v-%v", n.Op(), n.Linksym)
1100
1101 if n.Offset_ != 0 {
1102 fmt.Fprintf(w, "%+v", n.Offset_)
1103 }
1104 dumpNodeHeader(w, n)
1105
1106 case OASOP:
1107 n := n.(*AssignOpStmt)
1108 fmt.Fprintf(w, "%+v-%+v", n.Op(), n.AsOp)
1109 dumpNodeHeader(w, n)
1110
1111 case OTYPE:
1112 fmt.Fprintf(w, "%+v %+v", n.Op(), n.Sym())
1113 dumpNodeHeader(w, n)
1114 return
1115
1116 case OCLOSURE:
1117 fmt.Fprintf(w, "%+v", n.Op())
1118 dumpNodeHeader(w, n)
1119
1120 case ODCLFUNC:
1121
1122
1123 n := n.(*Func)
1124 fmt.Fprintf(w, "%+v", n.Op())
1125 dumpNodeHeader(w, n)
1126 fn := n
1127 if len(fn.Dcl) > 0 {
1128 indent(w, depth)
1129 fmt.Fprintf(w, "%+v-Dcl", n.Op())
1130 for _, dcl := range n.Dcl {
1131 dumpNode(w, dcl, depth+1)
1132 }
1133 }
1134 if len(fn.ClosureVars) > 0 {
1135 indent(w, depth)
1136 fmt.Fprintf(w, "%+v-ClosureVars", n.Op())
1137 for _, cv := range fn.ClosureVars {
1138 dumpNode(w, cv, depth+1)
1139 }
1140 }
1141 if len(fn.Body) > 0 {
1142 indent(w, depth)
1143 fmt.Fprintf(w, "%+v-body", n.Op())
1144 dumpNodes(w, fn.Body, depth+1)
1145 }
1146 return
1147 }
1148
1149 v := reflect.ValueOf(n).Elem()
1150 t := reflect.TypeOf(n).Elem()
1151 nf := t.NumField()
1152 for i := 0; i < nf; i++ {
1153 tf := t.Field(i)
1154 vf := v.Field(i)
1155 if tf.PkgPath != "" {
1156
1157 continue
1158 }
1159 switch tf.Type.Kind() {
1160 case reflect.Interface, reflect.Ptr, reflect.Slice:
1161 if vf.IsNil() {
1162 continue
1163 }
1164 }
1165 name := strings.TrimSuffix(tf.Name, "_")
1166
1167
1168
1169 switch name {
1170 case "X", "Y", "Index", "Chan", "Value", "Call":
1171 name = ""
1172 }
1173 switch val := vf.Interface().(type) {
1174 case Node:
1175 if name != "" {
1176 indent(w, depth)
1177 fmt.Fprintf(w, "%+v-%s", n.Op(), name)
1178 }
1179 dumpNode(w, val, depth+1)
1180 case Nodes:
1181 if len(val) == 0 {
1182 continue
1183 }
1184 if name != "" {
1185 indent(w, depth)
1186 fmt.Fprintf(w, "%+v-%s", n.Op(), name)
1187 }
1188 dumpNodes(w, val, depth+1)
1189 default:
1190 if vf.Kind() == reflect.Slice && vf.Type().Elem().Implements(nodeType) {
1191 if vf.Len() == 0 {
1192 continue
1193 }
1194 if name != "" {
1195 indent(w, depth)
1196 fmt.Fprintf(w, "%+v-%s", n.Op(), name)
1197 }
1198 for i, n := 0, vf.Len(); i < n; i++ {
1199 dumpNode(w, vf.Index(i).Interface().(Node), depth+1)
1200 }
1201 }
1202 }
1203 }
1204 }
1205
1206 var nodeType = reflect.TypeFor[Node]()
1207
1208 func dumpNodes(w io.Writer, list Nodes, depth int) {
1209 if len(list) == 0 {
1210 fmt.Fprintf(w, " <nil>")
1211 return
1212 }
1213
1214 for _, n := range list {
1215 dumpNode(w, n, depth)
1216 }
1217 }
1218
View as plain text