Source file src/pkg/cmd/compile/internal/gc/subr.go
1
2
3
4
5 package gc
6
7 import (
8 "cmd/compile/internal/types"
9 "cmd/internal/objabi"
10 "cmd/internal/src"
11 "crypto/md5"
12 "encoding/binary"
13 "fmt"
14 "os"
15 "runtime/debug"
16 "sort"
17 "strconv"
18 "strings"
19 "sync"
20 "unicode"
21 "unicode/utf8"
22 )
23
24 type Error struct {
25 pos src.XPos
26 msg string
27 }
28
29 var errors []Error
30
31
32 type largeStack struct {
33 locals int64
34 args int64
35 callee int64
36 pos src.XPos
37 }
38
39 var (
40 largeStackFramesMu sync.Mutex
41 largeStackFrames []largeStack
42 )
43
44 func errorexit() {
45 flusherrors()
46 if outfile != "" {
47 os.Remove(outfile)
48 }
49 os.Exit(2)
50 }
51
52 func adderrorname(n *Node) {
53 if n.Op != ODOT {
54 return
55 }
56 old := fmt.Sprintf("%v: undefined: %v\n", n.Line(), n.Left)
57 if len(errors) > 0 && errors[len(errors)-1].pos.Line() == n.Pos.Line() && errors[len(errors)-1].msg == old {
58 errors[len(errors)-1].msg = fmt.Sprintf("%v: undefined: %v in %v\n", n.Line(), n.Left, n)
59 }
60 }
61
62 func adderr(pos src.XPos, format string, args ...interface{}) {
63 errors = append(errors, Error{
64 pos: pos,
65 msg: fmt.Sprintf("%v: %s\n", linestr(pos), fmt.Sprintf(format, args...)),
66 })
67 }
68
69
70 type byPos []Error
71
72 func (x byPos) Len() int { return len(x) }
73 func (x byPos) Less(i, j int) bool { return x[i].pos.Before(x[j].pos) }
74 func (x byPos) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
75
76
77
78 func flusherrors() {
79 Ctxt.Bso.Flush()
80 if len(errors) == 0 {
81 return
82 }
83 sort.Stable(byPos(errors))
84 for i, err := range errors {
85 if i == 0 || err.msg != errors[i-1].msg {
86 fmt.Printf("%s", err.msg)
87 }
88 }
89 errors = errors[:0]
90 }
91
92 func hcrash() {
93 if Debug['h'] != 0 {
94 flusherrors()
95 if outfile != "" {
96 os.Remove(outfile)
97 }
98 var x *int
99 *x = 0
100 }
101 }
102
103 func linestr(pos src.XPos) string {
104 return Ctxt.OutermostPos(pos).Format(Debug['C'] == 0, Debug['L'] == 1)
105 }
106
107
108
109
110 var lasterror struct {
111 syntax src.XPos
112 other src.XPos
113 msg string
114 }
115
116
117 func sameline(a, b src.XPos) bool {
118 p := Ctxt.PosTable.Pos(a)
119 q := Ctxt.PosTable.Pos(b)
120 return p.Base() == q.Base() && p.Line() == q.Line()
121 }
122
123 func yyerrorl(pos src.XPos, format string, args ...interface{}) {
124 msg := fmt.Sprintf(format, args...)
125
126 if strings.HasPrefix(msg, "syntax error") {
127 nsyntaxerrors++
128
129 if sameline(lasterror.syntax, pos) {
130 return
131 }
132 lasterror.syntax = pos
133 } else {
134
135
136
137
138
139 if sameline(lasterror.other, pos) && lasterror.msg == msg {
140 return
141 }
142 lasterror.other = pos
143 lasterror.msg = msg
144 }
145
146 adderr(pos, "%s", msg)
147
148 hcrash()
149 nerrors++
150 if nsavederrors+nerrors >= 10 && Debug['e'] == 0 {
151 flusherrors()
152 fmt.Printf("%v: too many errors\n", linestr(pos))
153 errorexit()
154 }
155 }
156
157 func yyerrorv(lang string, format string, args ...interface{}) {
158 what := fmt.Sprintf(format, args...)
159 yyerrorl(lineno, "%s requires %s or later (-lang was set to %s; check go.mod)", what, lang, flag_lang)
160 }
161
162 func yyerror(format string, args ...interface{}) {
163 yyerrorl(lineno, format, args...)
164 }
165
166 func Warn(fmt_ string, args ...interface{}) {
167 Warnl(lineno, fmt_, args...)
168 }
169
170 func Warnl(line src.XPos, fmt_ string, args ...interface{}) {
171 adderr(line, fmt_, args...)
172 if Debug['m'] != 0 {
173 flusherrors()
174 }
175 }
176
177 func Fatalf(fmt_ string, args ...interface{}) {
178 flusherrors()
179
180 if Debug_panic != 0 || nsavederrors+nerrors == 0 {
181 fmt.Printf("%v: internal compiler error: ", linestr(lineno))
182 fmt.Printf(fmt_, args...)
183 fmt.Printf("\n")
184
185
186 if strings.HasPrefix(objabi.Version, "go") {
187 fmt.Printf("\n")
188 fmt.Printf("Please file a bug report including a short program that triggers the error.\n")
189 fmt.Printf("https://golang.org/issue/new\n")
190 } else {
191
192 fmt.Println()
193 os.Stdout.Write(debug.Stack())
194 fmt.Println()
195 }
196 }
197
198 hcrash()
199 errorexit()
200 }
201
202 func setlineno(n *Node) src.XPos {
203 lno := lineno
204 if n != nil {
205 switch n.Op {
206 case ONAME, OPACK:
207 break
208
209 case OLITERAL, OTYPE:
210 if n.Sym != nil {
211 break
212 }
213 fallthrough
214
215 default:
216 lineno = n.Pos
217 if !lineno.IsKnown() {
218 if Debug['K'] != 0 {
219 Warn("setlineno: unknown position (line 0)")
220 }
221 lineno = lno
222 }
223 }
224 }
225
226 return lno
227 }
228
229 func lookup(name string) *types.Sym {
230 return localpkg.Lookup(name)
231 }
232
233
234
235 func lookupN(prefix string, n int) *types.Sym {
236 var buf [20]byte
237 copy(buf[:], prefix)
238 b := strconv.AppendInt(buf[:len(prefix)], int64(n), 10)
239 return localpkg.LookupBytes(b)
240 }
241
242
243
244
245
246
247
248 func autolabel(prefix string) *types.Sym {
249 if prefix[0] != '.' {
250 Fatalf("autolabel prefix must start with '.', have %q", prefix)
251 }
252 fn := Curfn
253 if Curfn == nil {
254 Fatalf("autolabel outside function")
255 }
256 n := fn.Func.Label
257 fn.Func.Label++
258 return lookupN(prefix, int(n))
259 }
260
261 func restrictlookup(name string, pkg *types.Pkg) *types.Sym {
262 if !types.IsExported(name) && pkg != localpkg {
263 yyerror("cannot refer to unexported name %s.%s", pkg.Name, name)
264 }
265 return pkg.Lookup(name)
266 }
267
268
269
270 func importdot(opkg *types.Pkg, pack *Node) {
271 n := 0
272 for _, s := range opkg.Syms {
273 if s.Def == nil {
274 continue
275 }
276 if !types.IsExported(s.Name) || strings.ContainsRune(s.Name, 0xb7) {
277 continue
278 }
279 s1 := lookup(s.Name)
280 if s1.Def != nil {
281 pkgerror := fmt.Sprintf("during import %q", opkg.Path)
282 redeclare(lineno, s1, pkgerror)
283 continue
284 }
285
286 s1.Def = s.Def
287 s1.Block = s.Block
288 if asNode(s1.Def).Name == nil {
289 Dump("s1def", asNode(s1.Def))
290 Fatalf("missing Name")
291 }
292 asNode(s1.Def).Name.Pack = pack
293 s1.Origpkg = opkg
294 n++
295 }
296
297 if n == 0 {
298
299 yyerrorl(pack.Pos, "imported and not used: %q", opkg.Path)
300 }
301 }
302
303 func nod(op Op, nleft, nright *Node) *Node {
304 return nodl(lineno, op, nleft, nright)
305 }
306
307 func nodl(pos src.XPos, op Op, nleft, nright *Node) *Node {
308 var n *Node
309 switch op {
310 case OCLOSURE, ODCLFUNC:
311 var x struct {
312 n Node
313 f Func
314 }
315 n = &x.n
316 n.Func = &x.f
317 case ONAME:
318 Fatalf("use newname instead")
319 case OLABEL, OPACK:
320 var x struct {
321 n Node
322 m Name
323 }
324 n = &x.n
325 n.Name = &x.m
326 default:
327 n = new(Node)
328 }
329 n.Op = op
330 n.Left = nleft
331 n.Right = nright
332 n.Pos = pos
333 n.Xoffset = BADWIDTH
334 n.Orig = n
335 return n
336 }
337
338
339 func newname(s *types.Sym) *Node {
340 n := newnamel(lineno, s)
341 n.Name.Curfn = Curfn
342 return n
343 }
344
345
346
347 func newnamel(pos src.XPos, s *types.Sym) *Node {
348 if s == nil {
349 Fatalf("newnamel nil")
350 }
351
352 var x struct {
353 n Node
354 m Name
355 p Param
356 }
357 n := &x.n
358 n.Name = &x.m
359 n.Name.Param = &x.p
360
361 n.Op = ONAME
362 n.Pos = pos
363 n.Orig = n
364
365 n.Sym = s
366 n.SetAddable(true)
367 return n
368 }
369
370
371
372 func nodSym(op Op, left *Node, sym *types.Sym) *Node {
373 n := nod(op, left, nil)
374 n.Sym = sym
375 return n
376 }
377
378
379
380
381 func (n *Node) rawcopy() *Node {
382 copy := *n
383 return ©
384 }
385
386
387
388 func (n *Node) sepcopy() *Node {
389 copy := *n
390 copy.Orig = ©
391 return ©
392 }
393
394
395
396
397
398
399
400
401 func (n *Node) copy() *Node {
402 copy := *n
403 if n.Orig == n {
404 copy.Orig = ©
405 }
406 return ©
407 }
408
409
410 type methcmp []*types.Field
411
412 func (x methcmp) Len() int { return len(x) }
413 func (x methcmp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
414 func (x methcmp) Less(i, j int) bool { return x[i].Sym.Less(x[j].Sym) }
415
416 func nodintconst(v int64) *Node {
417 u := new(Mpint)
418 u.SetInt64(v)
419 return nodlit(Val{u})
420 }
421
422 func nodnil() *Node {
423 return nodlit(Val{new(NilVal)})
424 }
425
426 func nodbool(b bool) *Node {
427 return nodlit(Val{b})
428 }
429
430 func nodstr(s string) *Node {
431 return nodlit(Val{s})
432 }
433
434
435
436
437
438 func treecopy(n *Node, pos src.XPos) *Node {
439 if n == nil {
440 return nil
441 }
442
443 switch n.Op {
444 default:
445 m := n.sepcopy()
446 m.Left = treecopy(n.Left, pos)
447 m.Right = treecopy(n.Right, pos)
448 m.List.Set(listtreecopy(n.List.Slice(), pos))
449 if pos.IsKnown() {
450 m.Pos = pos
451 }
452 if m.Name != nil && n.Op != ODCLFIELD {
453 Dump("treecopy", n)
454 Fatalf("treecopy Name")
455 }
456 return m
457
458 case OPACK:
459
460
461
462 fallthrough
463
464 case ONAME, ONONAME, OLITERAL, OTYPE:
465 return n
466
467 }
468 }
469
470
471 func (n *Node) isNil() bool {
472
473
474 return Isconst(n.Orig, CTNIL)
475 }
476
477 func isptrto(t *types.Type, et types.EType) bool {
478 if t == nil {
479 return false
480 }
481 if !t.IsPtr() {
482 return false
483 }
484 t = t.Elem()
485 if t == nil {
486 return false
487 }
488 if t.Etype != et {
489 return false
490 }
491 return true
492 }
493
494 func (n *Node) isBlank() bool {
495 if n == nil {
496 return false
497 }
498 return n.Sym.IsBlank()
499 }
500
501
502
503
504 func methtype(t *types.Type) *types.Type {
505 if t == nil {
506 return nil
507 }
508
509
510 if t.IsPtr() {
511 if t.Sym != nil {
512 return nil
513 }
514 t = t.Elem()
515 if t == nil {
516 return nil
517 }
518 }
519
520
521 if t.Sym == nil && !t.IsStruct() {
522 return nil
523 }
524
525
526 if issimple[t.Etype] {
527 return t
528 }
529 switch t.Etype {
530 case TARRAY, TCHAN, TFUNC, TMAP, TSLICE, TSTRING, TSTRUCT:
531 return t
532 }
533 return nil
534 }
535
536
537
538
539 func assignop(src *types.Type, dst *types.Type, why *string) Op {
540 if why != nil {
541 *why = ""
542 }
543
544 if src == dst {
545 return OCONVNOP
546 }
547 if src == nil || dst == nil || src.Etype == TFORW || dst.Etype == TFORW || src.Orig == nil || dst.Orig == nil {
548 return 0
549 }
550
551
552 if types.Identical(src, dst) {
553 return OCONVNOP
554 }
555
556
557
558
559
560
561
562
563 if types.Identical(src.Orig, dst.Orig) {
564 if src.IsEmptyInterface() {
565
566
567 return OCONVNOP
568 }
569 if (src.Sym == nil || dst.Sym == nil) && !src.IsInterface() {
570
571
572
573 return OCONVNOP
574 }
575 }
576
577
578 if dst.IsInterface() && src.Etype != TNIL {
579 var missing, have *types.Field
580 var ptr int
581 if implements(src, dst, &missing, &have, &ptr) {
582 return OCONVIFACE
583 }
584
585
586 if have != nil && have.Sym == missing.Sym && (have.Type.Broke() || missing.Type.Broke()) {
587 return OCONVIFACE
588 }
589
590 if why != nil {
591 if isptrto(src, TINTER) {
592 *why = fmt.Sprintf(":\n\t%v is pointer to interface, not interface", src)
593 } else if have != nil && have.Sym == missing.Sym && have.Nointerface() {
594 *why = fmt.Sprintf(":\n\t%v does not implement %v (%v method is marked 'nointerface')", src, dst, missing.Sym)
595 } else if have != nil && have.Sym == missing.Sym {
596 *why = fmt.Sprintf(":\n\t%v does not implement %v (wrong type for %v method)\n"+
597 "\t\thave %v%0S\n\t\twant %v%0S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
598 } else if ptr != 0 {
599 *why = fmt.Sprintf(":\n\t%v does not implement %v (%v method has pointer receiver)", src, dst, missing.Sym)
600 } else if have != nil {
601 *why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)\n"+
602 "\t\thave %v%0S\n\t\twant %v%0S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
603 } else {
604 *why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)", src, dst, missing.Sym)
605 }
606 }
607
608 return 0
609 }
610
611 if isptrto(dst, TINTER) {
612 if why != nil {
613 *why = fmt.Sprintf(":\n\t%v is pointer to interface, not interface", dst)
614 }
615 return 0
616 }
617
618 if src.IsInterface() && dst.Etype != TBLANK {
619 var missing, have *types.Field
620 var ptr int
621 if why != nil && implements(dst, src, &missing, &have, &ptr) {
622 *why = ": need type assertion"
623 }
624 return 0
625 }
626
627
628
629
630 if src.IsChan() && src.ChanDir() == types.Cboth && dst.IsChan() {
631 if types.Identical(src.Elem(), dst.Elem()) && (src.Sym == nil || dst.Sym == nil) {
632 return OCONVNOP
633 }
634 }
635
636
637 if src.Etype == TNIL {
638 switch dst.Etype {
639 case TPTR,
640 TFUNC,
641 TMAP,
642 TCHAN,
643 TINTER,
644 TSLICE:
645 return OCONVNOP
646 }
647 }
648
649
650
651
652 if dst.Etype == TBLANK {
653 return OCONVNOP
654 }
655
656 return 0
657 }
658
659
660
661
662 func convertop(src *types.Type, dst *types.Type, why *string) Op {
663 if why != nil {
664 *why = ""
665 }
666
667 if src == dst {
668 return OCONVNOP
669 }
670 if src == nil || dst == nil {
671 return 0
672 }
673
674
675
676
677
678 if src.IsPtr() && dst.IsPtr() && dst.Elem().NotInHeap() && !src.Elem().NotInHeap() {
679 if why != nil {
680 *why = fmt.Sprintf(":\n\t%v is go:notinheap, but %v is not", dst.Elem(), src.Elem())
681 }
682 return 0
683 }
684
685 if src.IsString() && dst.IsSlice() && dst.Elem().NotInHeap() && (dst.Elem().Etype == types.Bytetype.Etype || dst.Elem().Etype == types.Runetype.Etype) {
686 if why != nil {
687 *why = fmt.Sprintf(":\n\t%v is go:notinheap", dst.Elem())
688 }
689 return 0
690 }
691
692
693 op := assignop(src, dst, why)
694 if op != 0 {
695 return op
696 }
697
698
699
700
701
702 if src.IsInterface() || dst.IsInterface() {
703 return 0
704 }
705 if why != nil {
706 *why = ""
707 }
708
709
710 if types.IdenticalIgnoreTags(src.Orig, dst.Orig) {
711 return OCONVNOP
712 }
713
714
715
716 if src.IsPtr() && dst.IsPtr() && src.Sym == nil && dst.Sym == nil {
717 if types.IdenticalIgnoreTags(src.Elem().Orig, dst.Elem().Orig) {
718 return OCONVNOP
719 }
720 }
721
722
723 if (src.IsInteger() || src.IsFloat()) && (dst.IsInteger() || dst.IsFloat()) {
724 if simtype[src.Etype] == simtype[dst.Etype] {
725 return OCONVNOP
726 }
727 return OCONV
728 }
729
730
731 if src.IsComplex() && dst.IsComplex() {
732 if simtype[src.Etype] == simtype[dst.Etype] {
733 return OCONVNOP
734 }
735 return OCONV
736 }
737
738
739
740 if src.IsInteger() && dst.IsString() {
741 return ORUNESTR
742 }
743
744 if src.IsSlice() && dst.IsString() {
745 if src.Elem().Etype == types.Bytetype.Etype {
746 return OBYTES2STR
747 }
748 if src.Elem().Etype == types.Runetype.Etype {
749 return ORUNES2STR
750 }
751 }
752
753
754
755 if src.IsString() && dst.IsSlice() {
756 if dst.Elem().Etype == types.Bytetype.Etype {
757 return OSTR2BYTES
758 }
759 if dst.Elem().Etype == types.Runetype.Etype {
760 return OSTR2RUNES
761 }
762 }
763
764
765 if (src.IsPtr() || src.Etype == TUINTPTR) && dst.Etype == TUNSAFEPTR {
766 return OCONVNOP
767 }
768
769
770 if src.Etype == TUNSAFEPTR && (dst.IsPtr() || dst.Etype == TUINTPTR) {
771 return OCONVNOP
772 }
773
774
775
776
777 if src.Etype == TMAP && dst.IsPtr() &&
778 src.MapType().Hmap == dst.Elem() {
779 return OCONVNOP
780 }
781
782 return 0
783 }
784
785 func assignconv(n *Node, t *types.Type, context string) *Node {
786 return assignconvfn(n, t, func() string { return context })
787 }
788
789
790 func assignconvfn(n *Node, t *types.Type, context func() string) *Node {
791 if n == nil || n.Type == nil || n.Type.Broke() {
792 return n
793 }
794
795 if t.Etype == TBLANK && n.Type.Etype == TNIL {
796 yyerror("use of untyped nil")
797 }
798
799 old := n
800 od := old.Diag()
801 old.SetDiag(true)
802 n = defaultlit(n, t)
803 old.SetDiag(od)
804 if t.Etype == TBLANK {
805 return n
806 }
807
808
809
810 if n.Type == types.Idealbool && !t.IsBoolean() {
811 if n.Op == ONAME || n.Op == OLITERAL {
812 r := nod(OCONVNOP, n, nil)
813 r.Type = types.Types[TBOOL]
814 r.SetTypecheck(1)
815 r.SetImplicit(true)
816 n = r
817 }
818 }
819
820 if types.Identical(n.Type, t) {
821 return n
822 }
823
824 var why string
825 op := assignop(n.Type, t, &why)
826 if op == 0 {
827 if !old.Diag() {
828 yyerror("cannot use %L as type %v in %s%s", n, t, context(), why)
829 }
830 op = OCONV
831 }
832
833 r := nod(op, n, nil)
834 r.Type = t
835 r.SetTypecheck(1)
836 r.SetImplicit(true)
837 r.Orig = n.Orig
838 return r
839 }
840
841
842
843 func (n *Node) IsMethod() bool {
844 return n.Type.Recv() != nil
845 }
846
847
848
849 func (n *Node) SliceBounds() (low, high, max *Node) {
850 if n.List.Len() == 0 {
851 return nil, nil, nil
852 }
853
854 switch n.Op {
855 case OSLICE, OSLICEARR, OSLICESTR:
856 s := n.List.Slice()
857 return s[0], s[1], nil
858 case OSLICE3, OSLICE3ARR:
859 s := n.List.Slice()
860 return s[0], s[1], s[2]
861 }
862 Fatalf("SliceBounds op %v: %v", n.Op, n)
863 return nil, nil, nil
864 }
865
866
867
868 func (n *Node) SetSliceBounds(low, high, max *Node) {
869 switch n.Op {
870 case OSLICE, OSLICEARR, OSLICESTR:
871 if max != nil {
872 Fatalf("SetSliceBounds %v given three bounds", n.Op)
873 }
874 s := n.List.Slice()
875 if s == nil {
876 if low == nil && high == nil {
877 return
878 }
879 n.List.Set2(low, high)
880 return
881 }
882 s[0] = low
883 s[1] = high
884 return
885 case OSLICE3, OSLICE3ARR:
886 s := n.List.Slice()
887 if s == nil {
888 if low == nil && high == nil && max == nil {
889 return
890 }
891 n.List.Set3(low, high, max)
892 return
893 }
894 s[0] = low
895 s[1] = high
896 s[2] = max
897 return
898 }
899 Fatalf("SetSliceBounds op %v: %v", n.Op, n)
900 }
901
902
903
904 func (o Op) IsSlice3() bool {
905 switch o {
906 case OSLICE, OSLICEARR, OSLICESTR:
907 return false
908 case OSLICE3, OSLICE3ARR:
909 return true
910 }
911 Fatalf("IsSlice3 op %v", o)
912 return false
913 }
914
915
916
917 func (n *Node) labeledControl() *Node {
918 if n.Op != OLABEL {
919 Fatalf("labeledControl %v", n.Op)
920 }
921 ctl := n.Name.Defn
922 if ctl == nil {
923 return nil
924 }
925 switch ctl.Op {
926 case OFOR, OFORUNTIL, OSWITCH, OSELECT:
927 return ctl
928 }
929 return nil
930 }
931
932 func syslook(name string) *Node {
933 s := Runtimepkg.Lookup(name)
934 if s == nil || s.Def == nil {
935 Fatalf("syslook: can't find runtime.%s", name)
936 }
937 return asNode(s.Def)
938 }
939
940
941 func typehash(t *types.Type) uint32 {
942 p := t.LongString()
943
944
945 h := md5.Sum([]byte(p))
946 return binary.LittleEndian.Uint32(h[:4])
947 }
948
949
950
951 func updateHasCall(n *Node) {
952 if n == nil {
953 return
954 }
955 n.SetHasCall(calcHasCall(n))
956 }
957
958 func calcHasCall(n *Node) bool {
959 if n.Ninit.Len() != 0 {
960
961 return true
962 }
963
964 switch n.Op {
965 case OLITERAL, ONAME, OTYPE:
966 if n.HasCall() {
967 Fatalf("OLITERAL/ONAME/OTYPE should never have calls: %+v", n)
968 }
969 return false
970 case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER:
971 return true
972 case OANDAND, OOROR:
973
974 if instrumenting {
975 return true
976 }
977 case OINDEX, OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR, OSLICESTR,
978 ODEREF, ODOTPTR, ODOTTYPE, ODIV, OMOD:
979
980
981 return true
982
983
984
985 case OADD, OSUB, ONEG, OMUL:
986 if thearch.SoftFloat && (isFloat[n.Type.Etype] || isComplex[n.Type.Etype]) {
987 return true
988 }
989 case OLT, OEQ, ONE, OLE, OGE, OGT:
990 if thearch.SoftFloat && (isFloat[n.Left.Type.Etype] || isComplex[n.Left.Type.Etype]) {
991 return true
992 }
993 case OCONV:
994 if thearch.SoftFloat && ((isFloat[n.Type.Etype] || isComplex[n.Type.Etype]) || (isFloat[n.Left.Type.Etype] || isComplex[n.Left.Type.Etype])) {
995 return true
996 }
997 }
998
999 if n.Left != nil && n.Left.HasCall() {
1000 return true
1001 }
1002 if n.Right != nil && n.Right.HasCall() {
1003 return true
1004 }
1005 return false
1006 }
1007
1008 func badtype(op Op, tl *types.Type, tr *types.Type) {
1009 fmt_ := ""
1010 if tl != nil {
1011 fmt_ += fmt.Sprintf("\n\t%v", tl)
1012 }
1013 if tr != nil {
1014 fmt_ += fmt.Sprintf("\n\t%v", tr)
1015 }
1016
1017
1018 if tl != nil && tr != nil && tl.IsPtr() && tr.IsPtr() {
1019 if tl.Elem().IsStruct() && tr.Elem().IsInterface() {
1020 fmt_ += "\n\t(*struct vs *interface)"
1021 } else if tl.Elem().IsInterface() && tr.Elem().IsStruct() {
1022 fmt_ += "\n\t(*interface vs *struct)"
1023 }
1024 }
1025
1026 s := fmt_
1027 yyerror("illegal types for operand: %v%s", op, s)
1028 }
1029
1030
1031
1032 func brcom(op Op) Op {
1033 switch op {
1034 case OEQ:
1035 return ONE
1036 case ONE:
1037 return OEQ
1038 case OLT:
1039 return OGE
1040 case OGT:
1041 return OLE
1042 case OLE:
1043 return OGT
1044 case OGE:
1045 return OLT
1046 }
1047 Fatalf("brcom: no com for %v\n", op)
1048 return op
1049 }
1050
1051
1052
1053 func brrev(op Op) Op {
1054 switch op {
1055 case OEQ:
1056 return OEQ
1057 case ONE:
1058 return ONE
1059 case OLT:
1060 return OGT
1061 case OGT:
1062 return OLT
1063 case OLE:
1064 return OGE
1065 case OGE:
1066 return OLE
1067 }
1068 Fatalf("brrev: no rev for %v\n", op)
1069 return op
1070 }
1071
1072
1073
1074 func safeexpr(n *Node, init *Nodes) *Node {
1075 if n == nil {
1076 return nil
1077 }
1078
1079 if n.Ninit.Len() != 0 {
1080 walkstmtlist(n.Ninit.Slice())
1081 init.AppendNodes(&n.Ninit)
1082 }
1083
1084 switch n.Op {
1085 case ONAME, OLITERAL:
1086 return n
1087
1088 case ODOT, OLEN, OCAP:
1089 l := safeexpr(n.Left, init)
1090 if l == n.Left {
1091 return n
1092 }
1093 r := n.copy()
1094 r.Left = l
1095 r = typecheck(r, ctxExpr)
1096 r = walkexpr(r, init)
1097 return r
1098
1099 case ODOTPTR, ODEREF:
1100 l := safeexpr(n.Left, init)
1101 if l == n.Left {
1102 return n
1103 }
1104 a := n.copy()
1105 a.Left = l
1106 a = walkexpr(a, init)
1107 return a
1108
1109 case OINDEX, OINDEXMAP:
1110 l := safeexpr(n.Left, init)
1111 r := safeexpr(n.Right, init)
1112 if l == n.Left && r == n.Right {
1113 return n
1114 }
1115 a := n.copy()
1116 a.Left = l
1117 a.Right = r
1118 a = walkexpr(a, init)
1119 return a
1120
1121 case OSTRUCTLIT, OARRAYLIT, OSLICELIT:
1122 if isStaticCompositeLiteral(n) {
1123 return n
1124 }
1125 }
1126
1127
1128 if islvalue(n) {
1129 Fatalf("missing lvalue case in safeexpr: %v", n)
1130 }
1131 return cheapexpr(n, init)
1132 }
1133
1134 func copyexpr(n *Node, t *types.Type, init *Nodes) *Node {
1135 l := temp(t)
1136 a := nod(OAS, l, n)
1137 a = typecheck(a, ctxStmt)
1138 a = walkexpr(a, init)
1139 init.Append(a)
1140 return l
1141 }
1142
1143
1144
1145 func cheapexpr(n *Node, init *Nodes) *Node {
1146 switch n.Op {
1147 case ONAME, OLITERAL:
1148 return n
1149 }
1150
1151 return copyexpr(n, n.Type, init)
1152 }
1153
1154
1155
1156
1157
1158 type Dlist struct {
1159 field *types.Field
1160 }
1161
1162
1163
1164
1165 var dotlist = make([]Dlist, 10)
1166
1167
1168
1169
1170 func lookdot0(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) int {
1171 u := t
1172 if u.IsPtr() {
1173 u = u.Elem()
1174 }
1175
1176 c := 0
1177 if u.IsStruct() || u.IsInterface() {
1178 for _, f := range u.Fields().Slice() {
1179 if f.Sym == s || (ignorecase && f.IsMethod() && strings.EqualFold(f.Sym.Name, s.Name)) {
1180 if save != nil {
1181 *save = f
1182 }
1183 c++
1184 }
1185 }
1186 }
1187
1188 u = methtype(t)
1189 if u != nil {
1190 for _, f := range u.Methods().Slice() {
1191 if f.Embedded == 0 && (f.Sym == s || (ignorecase && strings.EqualFold(f.Sym.Name, s.Name))) {
1192 if save != nil {
1193 *save = f
1194 }
1195 c++
1196 }
1197 }
1198 }
1199
1200 return c
1201 }
1202
1203
1204
1205
1206
1207
1208
1209 func adddot1(s *types.Sym, t *types.Type, d int, save **types.Field, ignorecase bool) (c int, more bool) {
1210 if t.Recur() {
1211 return
1212 }
1213 t.SetRecur(true)
1214 defer t.SetRecur(false)
1215
1216 var u *types.Type
1217 d--
1218 if d < 0 {
1219
1220
1221
1222 c = lookdot0(s, t, save, ignorecase)
1223 if c != 0 {
1224 return c, false
1225 }
1226 }
1227
1228 u = t
1229 if u.IsPtr() {
1230 u = u.Elem()
1231 }
1232 if !u.IsStruct() && !u.IsInterface() {
1233 return c, false
1234 }
1235
1236 for _, f := range u.Fields().Slice() {
1237 if f.Embedded == 0 || f.Sym == nil {
1238 continue
1239 }
1240 if d < 0 {
1241
1242 return c, true
1243 }
1244 a, more1 := adddot1(s, f.Type, d, save, ignorecase)
1245 if a != 0 && c == 0 {
1246 dotlist[d].field = f
1247 }
1248 c += a
1249 if more1 {
1250 more = true
1251 }
1252 }
1253
1254 return c, more
1255 }
1256
1257
1258
1259
1260
1261 func dotpath(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) (path []Dlist, ambig bool) {
1262
1263
1264
1265
1266
1267
1268 for d := 0; ; d++ {
1269 if d > len(dotlist) {
1270 dotlist = append(dotlist, Dlist{})
1271 }
1272 if c, more := adddot1(s, t, d, save, ignorecase); c == 1 {
1273 return dotlist[:d], false
1274 } else if c > 1 {
1275 return nil, true
1276 } else if !more {
1277 return nil, false
1278 }
1279 }
1280 }
1281
1282
1283
1284
1285
1286 func adddot(n *Node) *Node {
1287 n.Left = typecheck(n.Left, Etype|ctxExpr)
1288 if n.Left.Diag() {
1289 n.SetDiag(true)
1290 }
1291 t := n.Left.Type
1292 if t == nil {
1293 return n
1294 }
1295
1296 if n.Left.Op == OTYPE {
1297 return n
1298 }
1299
1300 s := n.Sym
1301 if s == nil {
1302 return n
1303 }
1304
1305 switch path, ambig := dotpath(s, t, nil, false); {
1306 case path != nil:
1307
1308 for c := len(path) - 1; c >= 0; c-- {
1309 n.Left = nodSym(ODOT, n.Left, path[c].field.Sym)
1310 n.Left.SetImplicit(true)
1311 }
1312 case ambig:
1313 yyerror("ambiguous selector %v", n)
1314 n.Left = nil
1315 }
1316
1317 return n
1318 }
1319
1320
1321
1322
1323
1324
1325 type Symlink struct {
1326 field *types.Field
1327 }
1328
1329 var slist []Symlink
1330
1331 func expand0(t *types.Type) {
1332 u := t
1333 if u.IsPtr() {
1334 u = u.Elem()
1335 }
1336
1337 if u.IsInterface() {
1338 for _, f := range u.Fields().Slice() {
1339 if f.Sym.Uniq() {
1340 continue
1341 }
1342 f.Sym.SetUniq(true)
1343 slist = append(slist, Symlink{field: f})
1344 }
1345
1346 return
1347 }
1348
1349 u = methtype(t)
1350 if u != nil {
1351 for _, f := range u.Methods().Slice() {
1352 if f.Sym.Uniq() {
1353 continue
1354 }
1355 f.Sym.SetUniq(true)
1356 slist = append(slist, Symlink{field: f})
1357 }
1358 }
1359 }
1360
1361 func expand1(t *types.Type, top bool) {
1362 if t.Recur() {
1363 return
1364 }
1365 t.SetRecur(true)
1366
1367 if !top {
1368 expand0(t)
1369 }
1370
1371 u := t
1372 if u.IsPtr() {
1373 u = u.Elem()
1374 }
1375
1376 if u.IsStruct() || u.IsInterface() {
1377 for _, f := range u.Fields().Slice() {
1378 if f.Embedded == 0 {
1379 continue
1380 }
1381 if f.Sym == nil {
1382 continue
1383 }
1384 expand1(f.Type, false)
1385 }
1386 }
1387
1388 t.SetRecur(false)
1389 }
1390
1391 func expandmeth(t *types.Type) {
1392 if t == nil || t.AllMethods().Len() != 0 {
1393 return
1394 }
1395
1396
1397
1398 for _, f := range t.Methods().Slice() {
1399 f.Sym.SetUniq(true)
1400 }
1401
1402
1403 slist = slist[:0]
1404 expand1(t, true)
1405
1406
1407 var ms []*types.Field
1408 for i, sl := range slist {
1409 slist[i].field = nil
1410 sl.field.Sym.SetUniq(false)
1411
1412 var f *types.Field
1413 path, _ := dotpath(sl.field.Sym, t, &f, false)
1414 if path == nil {
1415 continue
1416 }
1417
1418
1419 if !f.IsMethod() {
1420 continue
1421 }
1422
1423
1424 f = f.Copy()
1425 f.Embedded = 1
1426 for _, d := range path {
1427 if d.field.Type.IsPtr() {
1428 f.Embedded = 2
1429 break
1430 }
1431 }
1432 ms = append(ms, f)
1433 }
1434
1435 for _, f := range t.Methods().Slice() {
1436 f.Sym.SetUniq(false)
1437 }
1438
1439 ms = append(ms, t.Methods().Slice()...)
1440 sort.Sort(methcmp(ms))
1441 t.AllMethods().Set(ms)
1442 }
1443
1444
1445 func structargs(tl *types.Type, mustname bool) []*Node {
1446 var args []*Node
1447 gen := 0
1448 for _, t := range tl.Fields().Slice() {
1449 s := t.Sym
1450 if mustname && (s == nil || s.Name == "_") {
1451
1452 s = lookupN(".anon", gen)
1453 gen++
1454 }
1455 a := symfield(s, t.Type)
1456 a.Pos = t.Pos
1457 a.SetIsDDD(t.IsDDD())
1458 args = append(args, a)
1459 }
1460
1461 return args
1462 }
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485 func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
1486 if false && Debug['r'] != 0 {
1487 fmt.Printf("genwrapper rcvrtype=%v method=%v newnam=%v\n", rcvr, method, newnam)
1488 }
1489
1490
1491 if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type &&
1492 rcvr.Elem().Sym != nil && rcvr.Elem().Sym.Pkg != localpkg {
1493 return
1494 }
1495
1496
1497
1498 if rcvr.IsInterface() && rcvr.Sym != nil && rcvr.Sym.Pkg != localpkg && rcvr != types.Errortype {
1499 return
1500 }
1501
1502 lineno = autogeneratedPos
1503 dclcontext = PEXTERN
1504
1505 tfn := nod(OTFUNC, nil, nil)
1506 tfn.Left = namedfield(".this", rcvr)
1507 tfn.List.Set(structargs(method.Type.Params(), true))
1508 tfn.Rlist.Set(structargs(method.Type.Results(), false))
1509
1510 disableExport(newnam)
1511 fn := dclfunc(newnam, tfn)
1512 fn.Func.SetDupok(true)
1513
1514 nthis := asNode(tfn.Type.Recv().Nname)
1515
1516 methodrcvr := method.Type.Recv().Type
1517
1518
1519 if rcvr.IsPtr() && rcvr.Elem() == methodrcvr {
1520
1521 n := nod(OIF, nil, nil)
1522 n.Left = nod(OEQ, nthis, nodnil())
1523 call := nod(OCALL, syslook("panicwrap"), nil)
1524 n.Nbody.Set1(call)
1525 fn.Nbody.Append(n)
1526 }
1527
1528 dot := adddot(nodSym(OXDOT, nthis, method.Sym))
1529
1530
1531
1532
1533
1534
1535
1536
1537 if !instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !isifacemethod(method.Type) && !(thearch.LinkArch.Name == "ppc64le" && Ctxt.Flag_dynlink) {
1538
1539 dot = dot.Left
1540
1541 if !dotlist[0].field.Type.IsPtr() {
1542 dot = nod(OADDR, dot, nil)
1543 }
1544 as := nod(OAS, nthis, convnop(dot, rcvr))
1545 fn.Nbody.Append(as)
1546 fn.Nbody.Append(nodSym(ORETJMP, nil, methodSym(methodrcvr, method.Sym)))
1547 } else {
1548 fn.Func.SetWrapper(true)
1549 call := nod(OCALL, dot, nil)
1550 call.List.Set(paramNnames(tfn.Type))
1551 call.SetIsDDD(tfn.Type.IsVariadic())
1552 if method.Type.NumResults() > 0 {
1553 n := nod(ORETURN, nil, nil)
1554 n.List.Set1(call)
1555 call = n
1556 }
1557 fn.Nbody.Append(call)
1558 }
1559
1560 if false && Debug['r'] != 0 {
1561 dumplist("genwrapper body", fn.Nbody)
1562 }
1563
1564 funcbody()
1565 if debug_dclstack != 0 {
1566 testdclstack()
1567 }
1568
1569 fn = typecheck(fn, ctxStmt)
1570
1571 Curfn = fn
1572 typecheckslice(fn.Nbody.Slice(), ctxStmt)
1573
1574
1575
1576
1577 if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && rcvr.Elem().Sym != nil {
1578 inlcalls(fn)
1579 }
1580 escapeImpl()([]*Node{fn}, false)
1581
1582 Curfn = nil
1583 funccompile(fn)
1584 }
1585
1586 func paramNnames(ft *types.Type) []*Node {
1587 args := make([]*Node, ft.NumParams())
1588 for i, f := range ft.Params().FieldSlice() {
1589 args[i] = asNode(f.Nname)
1590 }
1591 return args
1592 }
1593
1594 func hashmem(t *types.Type) *Node {
1595 sym := Runtimepkg.Lookup("memhash")
1596
1597 n := newname(sym)
1598 n.SetClass(PFUNC)
1599 n.Sym.SetFunc(true)
1600 n.Type = functype(nil, []*Node{
1601 anonfield(types.NewPtr(t)),
1602 anonfield(types.Types[TUINTPTR]),
1603 anonfield(types.Types[TUINTPTR]),
1604 }, []*Node{
1605 anonfield(types.Types[TUINTPTR]),
1606 })
1607 return n
1608 }
1609
1610 func ifacelookdot(s *types.Sym, t *types.Type, ignorecase bool) (m *types.Field, followptr bool) {
1611 if t == nil {
1612 return nil, false
1613 }
1614
1615 path, ambig := dotpath(s, t, &m, ignorecase)
1616 if path == nil {
1617 if ambig {
1618 yyerror("%v.%v is ambiguous", t, s)
1619 }
1620 return nil, false
1621 }
1622
1623 for _, d := range path {
1624 if d.field.Type.IsPtr() {
1625 followptr = true
1626 break
1627 }
1628 }
1629
1630 if !m.IsMethod() {
1631 yyerror("%v.%v is a field, not a method", t, s)
1632 return nil, followptr
1633 }
1634
1635 return m, followptr
1636 }
1637
1638 func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool {
1639 t0 := t
1640 if t == nil {
1641 return false
1642 }
1643
1644 if t.IsInterface() {
1645 i := 0
1646 tms := t.Fields().Slice()
1647 for _, im := range iface.Fields().Slice() {
1648 for i < len(tms) && tms[i].Sym != im.Sym {
1649 i++
1650 }
1651 if i == len(tms) {
1652 *m = im
1653 *samename = nil
1654 *ptr = 0
1655 return false
1656 }
1657 tm := tms[i]
1658 if !types.Identical(tm.Type, im.Type) {
1659 *m = im
1660 *samename = tm
1661 *ptr = 0
1662 return false
1663 }
1664 }
1665
1666 return true
1667 }
1668
1669 t = methtype(t)
1670 var tms []*types.Field
1671 if t != nil {
1672 expandmeth(t)
1673 tms = t.AllMethods().Slice()
1674 }
1675 i := 0
1676 for _, im := range iface.Fields().Slice() {
1677 if im.Broke() {
1678 continue
1679 }
1680 for i < len(tms) && tms[i].Sym != im.Sym {
1681 i++
1682 }
1683 if i == len(tms) {
1684 *m = im
1685 *samename, _ = ifacelookdot(im.Sym, t, true)
1686 *ptr = 0
1687 return false
1688 }
1689 tm := tms[i]
1690 if tm.Nointerface() || !types.Identical(tm.Type, im.Type) {
1691 *m = im
1692 *samename = tm
1693 *ptr = 0
1694 return false
1695 }
1696 followptr := tm.Embedded == 2
1697
1698
1699
1700 rcvr := tm.Type.Recv().Type
1701 if rcvr.IsPtr() && !t0.IsPtr() && !followptr && !isifacemethod(tm.Type) {
1702 if false && Debug['r'] != 0 {
1703 yyerror("interface pointer mismatch")
1704 }
1705
1706 *m = im
1707 *samename = nil
1708 *ptr = 1
1709 return false
1710 }
1711 }
1712
1713
1714
1715
1716
1717
1718 if isdirectiface(t0) && !iface.IsEmptyInterface() {
1719 itabname(t0, iface)
1720 }
1721 return true
1722 }
1723
1724 func listtreecopy(l []*Node, pos src.XPos) []*Node {
1725 var out []*Node
1726 for _, n := range l {
1727 out = append(out, treecopy(n, pos))
1728 }
1729 return out
1730 }
1731
1732 func liststmt(l []*Node) *Node {
1733 n := nod(OBLOCK, nil, nil)
1734 n.List.Set(l)
1735 if len(l) != 0 {
1736 n.Pos = l[0].Pos
1737 }
1738 return n
1739 }
1740
1741 func (l Nodes) asblock() *Node {
1742 n := nod(OBLOCK, nil, nil)
1743 n.List = l
1744 if l.Len() != 0 {
1745 n.Pos = l.First().Pos
1746 }
1747 return n
1748 }
1749
1750 func ngotype(n *Node) *types.Sym {
1751 if n.Type != nil {
1752 return typenamesym(n.Type)
1753 }
1754 return nil
1755 }
1756
1757
1758
1759 func addinit(n *Node, init []*Node) *Node {
1760 if len(init) == 0 {
1761 return n
1762 }
1763 if n.mayBeShared() {
1764
1765 n = nod(OCONVNOP, n, nil)
1766 n.Type = n.Left.Type
1767 n.SetTypecheck(1)
1768 }
1769
1770 n.Ninit.Prepend(init...)
1771 n.SetHasCall(true)
1772 return n
1773 }
1774
1775
1776
1777
1778
1779
1780 var reservedimports = []string{
1781 "go",
1782 "type",
1783 }
1784
1785 func isbadimport(path string, allowSpace bool) bool {
1786 if strings.Contains(path, "\x00") {
1787 yyerror("import path contains NUL")
1788 return true
1789 }
1790
1791 for _, ri := range reservedimports {
1792 if path == ri {
1793 yyerror("import path %q is reserved and cannot be used", path)
1794 return true
1795 }
1796 }
1797
1798 for _, r := range path {
1799 if r == utf8.RuneError {
1800 yyerror("import path contains invalid UTF-8 sequence: %q", path)
1801 return true
1802 }
1803
1804 if r < 0x20 || r == 0x7f {
1805 yyerror("import path contains control character: %q", path)
1806 return true
1807 }
1808
1809 if r == '\\' {
1810 yyerror("import path contains backslash; use slash: %q", path)
1811 return true
1812 }
1813
1814 if !allowSpace && unicode.IsSpace(r) {
1815 yyerror("import path contains space character: %q", path)
1816 return true
1817 }
1818
1819 if strings.ContainsRune("!\"#$%&'()*,:;<=>?[]^`{|}", r) {
1820 yyerror("import path contains invalid character '%c': %q", r, path)
1821 return true
1822 }
1823 }
1824
1825 return false
1826 }
1827
1828
1829
1830 func isdirectiface(t *types.Type) bool {
1831 if t.Broke() {
1832 return false
1833 }
1834
1835 switch t.Etype {
1836 case TPTR,
1837 TCHAN,
1838 TMAP,
1839 TFUNC,
1840 TUNSAFEPTR:
1841 return true
1842
1843 case TARRAY:
1844
1845 return t.NumElem() == 1 && isdirectiface(t.Elem())
1846
1847 case TSTRUCT:
1848
1849 return t.NumFields() == 1 && isdirectiface(t.Field(0).Type)
1850 }
1851
1852 return false
1853 }
1854
1855
1856 func itabType(itab *Node) *Node {
1857 typ := nodSym(ODOTPTR, itab, nil)
1858 typ.Type = types.NewPtr(types.Types[TUINT8])
1859 typ.SetTypecheck(1)
1860 typ.Xoffset = int64(Widthptr)
1861 typ.SetBounded(true)
1862 return typ
1863 }
1864
1865
1866
1867
1868 func ifaceData(n *Node, t *types.Type) *Node {
1869 ptr := nodSym(OIDATA, n, nil)
1870 if isdirectiface(t) {
1871 ptr.Type = t
1872 ptr.SetTypecheck(1)
1873 return ptr
1874 }
1875 ptr.Type = types.NewPtr(t)
1876 ptr.SetBounded(true)
1877 ptr.SetTypecheck(1)
1878 ind := nod(ODEREF, ptr, nil)
1879 ind.Type = t
1880 ind.SetTypecheck(1)
1881 return ind
1882 }
1883
View as plain text