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