1
2
3
4
5 package ir
6
7 import (
8 "bytes"
9 "cmd/compile/internal/base"
10 "cmd/compile/internal/types"
11 "cmd/internal/obj"
12 "cmd/internal/src"
13 "fmt"
14 "go/constant"
15 "go/token"
16 )
17
18
19 type Expr interface {
20 Node
21 isExpr()
22 }
23
24
25
26
27
28 type miniExpr struct {
29 miniNode
30 flags bitset8
31 typ *types.Type
32 init Nodes
33 }
34
35 const (
36 miniExprNonNil = 1 << iota
37 miniExprTransient
38 miniExprBounded
39 miniExprImplicit
40 miniExprCheckPtr
41 )
42
43 func (*miniExpr) isExpr() {}
44
45 func (n *miniExpr) Type() *types.Type { return n.typ }
46 func (n *miniExpr) SetType(x *types.Type) { n.typ = x }
47 func (n *miniExpr) NonNil() bool { return n.flags&miniExprNonNil != 0 }
48 func (n *miniExpr) MarkNonNil() { n.flags |= miniExprNonNil }
49 func (n *miniExpr) Transient() bool { return n.flags&miniExprTransient != 0 }
50 func (n *miniExpr) SetTransient(b bool) { n.flags.set(miniExprTransient, b) }
51 func (n *miniExpr) Bounded() bool { return n.flags&miniExprBounded != 0 }
52 func (n *miniExpr) SetBounded(b bool) { n.flags.set(miniExprBounded, b) }
53 func (n *miniExpr) Init() Nodes { return n.init }
54 func (n *miniExpr) PtrInit() *Nodes { return &n.init }
55 func (n *miniExpr) SetInit(x Nodes) { n.init = x }
56
57
58 type AddStringExpr struct {
59 miniExpr
60 List Nodes
61 Prealloc *Name
62 }
63
64 func NewAddStringExpr(pos src.XPos, list []Node) *AddStringExpr {
65 n := &AddStringExpr{}
66 n.pos = pos
67 n.op = OADDSTR
68 n.List = list
69 return n
70 }
71
72
73
74 type AddrExpr struct {
75 miniExpr
76 X Node
77 Prealloc *Name
78 }
79
80 func NewAddrExpr(pos src.XPos, x Node) *AddrExpr {
81 if x == nil || x.Typecheck() != 1 {
82 base.FatalfAt(pos, "missed typecheck: %L", x)
83 }
84 n := &AddrExpr{X: x}
85 n.pos = pos
86
87 switch x.Op() {
88 case OARRAYLIT, OMAPLIT, OSLICELIT, OSTRUCTLIT:
89 n.op = OPTRLIT
90
91 default:
92 n.op = OADDR
93 if r, ok := OuterValue(x).(*Name); ok && r.Op() == ONAME {
94 r.SetAddrtaken(true)
95
96
97
98
99
100
101
102
103
104
105 if r.IsClosureVar() && !r.Byval() {
106 r.Canonical().SetAddrtaken(true)
107 }
108 }
109 }
110
111 n.SetType(types.NewPtr(x.Type()))
112 n.SetTypecheck(1)
113
114 return n
115 }
116
117 func (n *AddrExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
118 func (n *AddrExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
119
120 func (n *AddrExpr) SetOp(op Op) {
121 switch op {
122 default:
123 panic(n.no("SetOp " + op.String()))
124 case OADDR, OPTRLIT:
125 n.op = op
126 }
127 }
128
129
130 type BasicLit struct {
131 miniExpr
132 val constant.Value
133 }
134
135
136 func NewBasicLit(pos src.XPos, typ *types.Type, val constant.Value) Node {
137 AssertValidTypeForConst(typ, val)
138
139 n := &BasicLit{val: val}
140 n.op = OLITERAL
141 n.pos = pos
142 n.SetType(typ)
143 n.SetTypecheck(1)
144 return n
145 }
146
147 func (n *BasicLit) Val() constant.Value { return n.val }
148 func (n *BasicLit) SetVal(val constant.Value) { n.val = val }
149
150
151
152 func NewConstExpr(val constant.Value, orig Node) Node {
153 return NewBasicLit(orig.Pos(), orig.Type(), val)
154 }
155
156
157
158 type BinaryExpr struct {
159 miniExpr
160 X Node
161 Y Node
162 RType Node `mknode:"-"`
163 }
164
165 func NewBinaryExpr(pos src.XPos, op Op, x, y Node) *BinaryExpr {
166 n := &BinaryExpr{X: x, Y: y}
167 n.pos = pos
168 n.SetOp(op)
169 return n
170 }
171
172 func (n *BinaryExpr) SetOp(op Op) {
173 switch op {
174 default:
175 panic(n.no("SetOp " + op.String()))
176 case OADD, OADDSTR, OAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE,
177 OLSH, OLT, OMOD, OMUL, ONE, OOR, ORSH, OSUB, OXOR,
178 OCOPY, OCOMPLEX, OUNSAFEADD, OUNSAFESLICE, OUNSAFESTRING,
179 OMAKEFACE:
180 n.op = op
181 }
182 }
183
184
185 type CallExpr struct {
186 miniExpr
187 Fun Node
188 Args Nodes
189 DeferAt Node
190 RType Node `mknode:"-"`
191 KeepAlive []*Name
192 IsDDD bool
193 GoDefer bool
194 NoInline bool
195 }
196
197 func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr {
198 n := &CallExpr{Fun: fun}
199 n.pos = pos
200 n.SetOp(op)
201 n.Args = args
202 return n
203 }
204
205 func (*CallExpr) isStmt() {}
206
207 func (n *CallExpr) SetOp(op Op) {
208 switch op {
209 default:
210 panic(n.no("SetOp " + op.String()))
211 case OAPPEND,
212 OCALL, OCALLFUNC, OCALLINTER, OCALLMETH,
213 ODELETE,
214 OGETG, OGETCALLERSP,
215 OMAKE, OMAX, OMIN, OPRINT, OPRINTLN,
216 ORECOVER, ORECOVERFP:
217 n.op = op
218 }
219 }
220
221
222 type ClosureExpr struct {
223 miniExpr
224 Func *Func `mknode:"-"`
225 Prealloc *Name
226 IsGoWrap bool
227 }
228
229
230
231 type CompLitExpr struct {
232 miniExpr
233 List Nodes
234 RType Node `mknode:"-"`
235 Prealloc *Name
236
237
238
239 Len int64
240 }
241
242 func NewCompLitExpr(pos src.XPos, op Op, typ *types.Type, list []Node) *CompLitExpr {
243 n := &CompLitExpr{List: list}
244 n.pos = pos
245 n.SetOp(op)
246 if typ != nil {
247 n.SetType(typ)
248 }
249 return n
250 }
251
252 func (n *CompLitExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
253 func (n *CompLitExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
254
255 func (n *CompLitExpr) SetOp(op Op) {
256 switch op {
257 default:
258 panic(n.no("SetOp " + op.String()))
259 case OARRAYLIT, OCOMPLIT, OMAPLIT, OSTRUCTLIT, OSLICELIT:
260 n.op = op
261 }
262 }
263
264
265
266 type ConvExpr struct {
267 miniExpr
268 X Node
269
270
271
272
273
274
275
276
277
278 TypeWord Node `mknode:"-"`
279 SrcRType Node `mknode:"-"`
280
281
282
283
284
285
286
287
288 ElemRType Node `mknode:"-"`
289 ElemElemRType Node `mknode:"-"`
290 }
291
292 func NewConvExpr(pos src.XPos, op Op, typ *types.Type, x Node) *ConvExpr {
293 n := &ConvExpr{X: x}
294 n.pos = pos
295 n.typ = typ
296 n.SetOp(op)
297 return n
298 }
299
300 func (n *ConvExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
301 func (n *ConvExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
302 func (n *ConvExpr) CheckPtr() bool { return n.flags&miniExprCheckPtr != 0 }
303 func (n *ConvExpr) SetCheckPtr(b bool) { n.flags.set(miniExprCheckPtr, b) }
304
305 func (n *ConvExpr) SetOp(op Op) {
306 switch op {
307 default:
308 panic(n.no("SetOp " + op.String()))
309 case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, OBYTES2STRTMP, ORUNES2STR, OSTR2BYTES, OSTR2BYTESTMP, OSTR2RUNES, ORUNESTR, OSLICE2ARR, OSLICE2ARRPTR:
310 n.op = op
311 }
312 }
313
314
315 type IndexExpr struct {
316 miniExpr
317 X Node
318 Index Node
319 RType Node `mknode:"-"`
320 Assigned bool
321 }
322
323 func NewIndexExpr(pos src.XPos, x, index Node) *IndexExpr {
324 n := &IndexExpr{X: x, Index: index}
325 n.pos = pos
326 n.op = OINDEX
327 return n
328 }
329
330 func (n *IndexExpr) SetOp(op Op) {
331 switch op {
332 default:
333 panic(n.no("SetOp " + op.String()))
334 case OINDEX, OINDEXMAP:
335 n.op = op
336 }
337 }
338
339
340 type KeyExpr struct {
341 miniExpr
342 Key Node
343 Value Node
344 }
345
346 func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr {
347 n := &KeyExpr{Key: key, Value: value}
348 n.pos = pos
349 n.op = OKEY
350 return n
351 }
352
353
354 type StructKeyExpr struct {
355 miniExpr
356 Field *types.Field
357 Value Node
358 }
359
360 func NewStructKeyExpr(pos src.XPos, field *types.Field, value Node) *StructKeyExpr {
361 n := &StructKeyExpr{Field: field, Value: value}
362 n.pos = pos
363 n.op = OSTRUCTKEY
364 return n
365 }
366
367 func (n *StructKeyExpr) Sym() *types.Sym { return n.Field.Sym }
368
369
370 type InlinedCallExpr struct {
371 miniExpr
372 Body Nodes
373 ReturnVars Nodes
374 }
375
376 func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr {
377 n := &InlinedCallExpr{}
378 n.pos = pos
379 n.op = OINLCALL
380 n.Body = body
381 n.ReturnVars = retvars
382 return n
383 }
384
385 func (n *InlinedCallExpr) SingleResult() Node {
386 if have := len(n.ReturnVars); have != 1 {
387 base.FatalfAt(n.Pos(), "inlined call has %v results, expected 1", have)
388 }
389 if !n.Type().HasShape() && n.ReturnVars[0].Type().HasShape() {
390
391
392
393 r := NewConvExpr(n.Pos(), OCONVNOP, n.Type(), n.ReturnVars[0])
394 r.SetTypecheck(1)
395 return r
396 }
397 return n.ReturnVars[0]
398 }
399
400
401
402
403 type LogicalExpr struct {
404 miniExpr
405 X Node
406 Y Node
407 }
408
409 func NewLogicalExpr(pos src.XPos, op Op, x, y Node) *LogicalExpr {
410 n := &LogicalExpr{X: x, Y: y}
411 n.pos = pos
412 n.SetOp(op)
413 return n
414 }
415
416 func (n *LogicalExpr) SetOp(op Op) {
417 switch op {
418 default:
419 panic(n.no("SetOp " + op.String()))
420 case OANDAND, OOROR:
421 n.op = op
422 }
423 }
424
425
426
427
428 type MakeExpr struct {
429 miniExpr
430 RType Node `mknode:"-"`
431 Len Node
432 Cap Node
433 }
434
435 func NewMakeExpr(pos src.XPos, op Op, len, cap Node) *MakeExpr {
436 n := &MakeExpr{Len: len, Cap: cap}
437 n.pos = pos
438 n.SetOp(op)
439 return n
440 }
441
442 func (n *MakeExpr) SetOp(op Op) {
443 switch op {
444 default:
445 panic(n.no("SetOp " + op.String()))
446 case OMAKECHAN, OMAKEMAP, OMAKESLICE, OMAKESLICECOPY:
447 n.op = op
448 }
449 }
450
451
452 type NilExpr struct {
453 miniExpr
454 }
455
456 func NewNilExpr(pos src.XPos, typ *types.Type) *NilExpr {
457 if typ == nil {
458 base.FatalfAt(pos, "missing type")
459 }
460 n := &NilExpr{}
461 n.pos = pos
462 n.op = ONIL
463 n.SetType(typ)
464 n.SetTypecheck(1)
465 return n
466 }
467
468
469
470 type ParenExpr struct {
471 miniExpr
472 X Node
473 }
474
475 func NewParenExpr(pos src.XPos, x Node) *ParenExpr {
476 n := &ParenExpr{X: x}
477 n.op = OPAREN
478 n.pos = pos
479 return n
480 }
481
482 func (n *ParenExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
483 func (n *ParenExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
484
485
486 type ResultExpr struct {
487 miniExpr
488 Index int64
489 }
490
491 func NewResultExpr(pos src.XPos, typ *types.Type, index int64) *ResultExpr {
492 n := &ResultExpr{Index: index}
493 n.pos = pos
494 n.op = ORESULT
495 n.typ = typ
496 return n
497 }
498
499
500
501 type LinksymOffsetExpr struct {
502 miniExpr
503 Linksym *obj.LSym
504 Offset_ int64
505 }
506
507 func NewLinksymOffsetExpr(pos src.XPos, lsym *obj.LSym, offset int64, typ *types.Type) *LinksymOffsetExpr {
508 if typ == nil {
509 base.FatalfAt(pos, "nil type")
510 }
511 n := &LinksymOffsetExpr{Linksym: lsym, Offset_: offset}
512 n.typ = typ
513 n.op = OLINKSYMOFFSET
514 n.SetTypecheck(1)
515 return n
516 }
517
518
519 func NewLinksymExpr(pos src.XPos, lsym *obj.LSym, typ *types.Type) *LinksymOffsetExpr {
520 return NewLinksymOffsetExpr(pos, lsym, 0, typ)
521 }
522
523
524
525 func NewNameOffsetExpr(pos src.XPos, name *Name, offset int64, typ *types.Type) *LinksymOffsetExpr {
526 if name == nil || IsBlank(name) || !(name.Op() == ONAME && name.Class == PEXTERN) {
527 base.FatalfAt(pos, "cannot take offset of nil, blank name or non-global variable: %v", name)
528 }
529 return NewLinksymOffsetExpr(pos, name.Linksym(), offset, typ)
530 }
531
532
533 type SelectorExpr struct {
534 miniExpr
535 X Node
536
537
538
539
540 Sel *types.Sym
541
542 Selection *types.Field
543 Prealloc *Name
544 }
545
546 func NewSelectorExpr(pos src.XPos, op Op, x Node, sel *types.Sym) *SelectorExpr {
547 n := &SelectorExpr{X: x, Sel: sel}
548 n.pos = pos
549 n.SetOp(op)
550 return n
551 }
552
553 func (n *SelectorExpr) SetOp(op Op) {
554 switch op {
555 default:
556 panic(n.no("SetOp " + op.String()))
557 case OXDOT, ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OMETHVALUE, OMETHEXPR:
558 n.op = op
559 }
560 }
561
562 func (n *SelectorExpr) Sym() *types.Sym { return n.Sel }
563 func (n *SelectorExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
564 func (n *SelectorExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
565 func (n *SelectorExpr) Offset() int64 { return n.Selection.Offset }
566
567 func (n *SelectorExpr) FuncName() *Name {
568 if n.Op() != OMETHEXPR {
569 panic(n.no("FuncName"))
570 }
571 fn := NewNameAt(n.Selection.Pos, MethodSym(n.X.Type(), n.Sel), n.Type())
572 fn.Class = PFUNC
573 if n.Selection.Nname != nil {
574
575
576
577 fn.Func = n.Selection.Nname.(*Name).Func
578 }
579 return fn
580 }
581
582
583 type SliceExpr struct {
584 miniExpr
585 X Node
586 Low Node
587 High Node
588 Max Node
589 }
590
591 func NewSliceExpr(pos src.XPos, op Op, x, low, high, max Node) *SliceExpr {
592 n := &SliceExpr{X: x, Low: low, High: high, Max: max}
593 n.pos = pos
594 n.op = op
595 return n
596 }
597
598 func (n *SliceExpr) SetOp(op Op) {
599 switch op {
600 default:
601 panic(n.no("SetOp " + op.String()))
602 case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
603 n.op = op
604 }
605 }
606
607
608
609 func (o Op) IsSlice3() bool {
610 switch o {
611 case OSLICE, OSLICEARR, OSLICESTR:
612 return false
613 case OSLICE3, OSLICE3ARR:
614 return true
615 }
616 base.Fatalf("IsSlice3 op %v", o)
617 return false
618 }
619
620
621 type SliceHeaderExpr struct {
622 miniExpr
623 Ptr Node
624 Len Node
625 Cap Node
626 }
627
628 func NewSliceHeaderExpr(pos src.XPos, typ *types.Type, ptr, len, cap Node) *SliceHeaderExpr {
629 n := &SliceHeaderExpr{Ptr: ptr, Len: len, Cap: cap}
630 n.pos = pos
631 n.op = OSLICEHEADER
632 n.typ = typ
633 return n
634 }
635
636
637 type StringHeaderExpr struct {
638 miniExpr
639 Ptr Node
640 Len Node
641 }
642
643 func NewStringHeaderExpr(pos src.XPos, ptr, len Node) *StringHeaderExpr {
644 n := &StringHeaderExpr{Ptr: ptr, Len: len}
645 n.pos = pos
646 n.op = OSTRINGHEADER
647 n.typ = types.Types[types.TSTRING]
648 return n
649 }
650
651
652
653 type StarExpr struct {
654 miniExpr
655 X Node
656 }
657
658 func NewStarExpr(pos src.XPos, x Node) *StarExpr {
659 n := &StarExpr{X: x}
660 n.op = ODEREF
661 n.pos = pos
662 return n
663 }
664
665 func (n *StarExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
666 func (n *StarExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
667
668
669
670 type TypeAssertExpr struct {
671 miniExpr
672 X Node
673
674
675
676 ITab Node `mknode:"-"`
677
678
679 Descriptor *obj.LSym
680 }
681
682 func NewTypeAssertExpr(pos src.XPos, x Node, typ *types.Type) *TypeAssertExpr {
683 n := &TypeAssertExpr{X: x}
684 n.pos = pos
685 n.op = ODOTTYPE
686 if typ != nil {
687 n.SetType(typ)
688 }
689 return n
690 }
691
692 func (n *TypeAssertExpr) SetOp(op Op) {
693 switch op {
694 default:
695 panic(n.no("SetOp " + op.String()))
696 case ODOTTYPE, ODOTTYPE2:
697 n.op = op
698 }
699 }
700
701
702 type DynamicTypeAssertExpr struct {
703 miniExpr
704 X Node
705
706
707
708
709 SrcRType Node
710
711
712
713
714
715 RType Node
716
717
718
719
720
721
722
723
724 ITab Node
725 }
726
727 func NewDynamicTypeAssertExpr(pos src.XPos, op Op, x, rtype Node) *DynamicTypeAssertExpr {
728 n := &DynamicTypeAssertExpr{X: x, RType: rtype}
729 n.pos = pos
730 n.op = op
731 return n
732 }
733
734 func (n *DynamicTypeAssertExpr) SetOp(op Op) {
735 switch op {
736 default:
737 panic(n.no("SetOp " + op.String()))
738 case ODYNAMICDOTTYPE, ODYNAMICDOTTYPE2:
739 n.op = op
740 }
741 }
742
743
744
745 type UnaryExpr struct {
746 miniExpr
747 X Node
748 }
749
750 func NewUnaryExpr(pos src.XPos, op Op, x Node) *UnaryExpr {
751 n := &UnaryExpr{X: x}
752 n.pos = pos
753 n.SetOp(op)
754 return n
755 }
756
757 func (n *UnaryExpr) SetOp(op Op) {
758 switch op {
759 default:
760 panic(n.no("SetOp " + op.String()))
761 case OBITNOT, ONEG, ONOT, OPLUS, ORECV,
762 OCAP, OCLEAR, OCLOSE, OIMAG, OLEN, ONEW, OPANIC, OREAL,
763 OCHECKNIL, OCFUNC, OIDATA, OITAB, OSPTR,
764 OUNSAFESTRINGDATA, OUNSAFESLICEDATA:
765 n.op = op
766 }
767 }
768
769 func IsZero(n Node) bool {
770 switch n.Op() {
771 case ONIL:
772 return true
773
774 case OLITERAL:
775 switch u := n.Val(); u.Kind() {
776 case constant.String:
777 return constant.StringVal(u) == ""
778 case constant.Bool:
779 return !constant.BoolVal(u)
780 default:
781 return constant.Sign(u) == 0
782 }
783
784 case OARRAYLIT:
785 n := n.(*CompLitExpr)
786 for _, n1 := range n.List {
787 if n1.Op() == OKEY {
788 n1 = n1.(*KeyExpr).Value
789 }
790 if !IsZero(n1) {
791 return false
792 }
793 }
794 return true
795
796 case OSTRUCTLIT:
797 n := n.(*CompLitExpr)
798 for _, n1 := range n.List {
799 n1 := n1.(*StructKeyExpr)
800 if !IsZero(n1.Value) {
801 return false
802 }
803 }
804 return true
805 }
806
807 return false
808 }
809
810
811 func IsAddressable(n Node) bool {
812 switch n.Op() {
813 case OINDEX:
814 n := n.(*IndexExpr)
815 if n.X.Type() != nil && n.X.Type().IsArray() {
816 return IsAddressable(n.X)
817 }
818 if n.X.Type() != nil && n.X.Type().IsString() {
819 return false
820 }
821 fallthrough
822 case ODEREF, ODOTPTR:
823 return true
824
825 case ODOT:
826 n := n.(*SelectorExpr)
827 return IsAddressable(n.X)
828
829 case ONAME:
830 n := n.(*Name)
831 if n.Class == PFUNC {
832 return false
833 }
834 return true
835
836 case OLINKSYMOFFSET:
837 return true
838 }
839
840 return false
841 }
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861 func StaticValue(n Node) Node {
862 for {
863 switch n1 := n.(type) {
864 case *ConvExpr:
865 if n1.Op() == OCONVNOP {
866 n = n1.X
867 continue
868 }
869 case *InlinedCallExpr:
870 if n1.Op() == OINLCALL {
871 n = n1.SingleResult()
872 continue
873 }
874 case *ParenExpr:
875 n = n1.X
876 continue
877 }
878
879 n1 := staticValue1(n)
880 if n1 == nil {
881 return n
882 }
883 n = n1
884 }
885 }
886
887 func staticValue1(nn Node) Node {
888 if nn.Op() != ONAME {
889 return nil
890 }
891 n := nn.(*Name).Canonical()
892 if n.Class != PAUTO {
893 return nil
894 }
895
896 defn := n.Defn
897 if defn == nil {
898 return nil
899 }
900
901 var rhs Node
902 FindRHS:
903 switch defn.Op() {
904 case OAS:
905 defn := defn.(*AssignStmt)
906 rhs = defn.Y
907 case OAS2:
908 defn := defn.(*AssignListStmt)
909 for i, lhs := range defn.Lhs {
910 if lhs == n {
911 rhs = defn.Rhs[i]
912 break FindRHS
913 }
914 }
915 base.Fatalf("%v missing from LHS of %v", n, defn)
916 default:
917 return nil
918 }
919 if rhs == nil {
920 base.Fatalf("RHS is nil: %v", defn)
921 }
922
923 if Reassigned(n) {
924 return nil
925 }
926
927 return rhs
928 }
929
930
931
932
933
934
935
936
937
938 func Reassigned(name *Name) bool {
939 if name.Op() != ONAME {
940 base.Fatalf("reassigned %v", name)
941 }
942
943 if name.Curfn == nil {
944 return true
945 }
946
947 if name.Addrtaken() {
948 return true
949 }
950
951
952
953
954
955
956 isName := func(x Node) bool {
957 if x == nil {
958 return false
959 }
960 n, ok := OuterValue(x).(*Name)
961 return ok && n.Canonical() == name
962 }
963
964 var do func(n Node) bool
965 do = func(n Node) bool {
966 switch n.Op() {
967 case OAS:
968 n := n.(*AssignStmt)
969 if isName(n.X) && n != name.Defn {
970 return true
971 }
972 case OAS2, OAS2FUNC, OAS2MAPR, OAS2DOTTYPE, OAS2RECV, OSELRECV2:
973 n := n.(*AssignListStmt)
974 for _, p := range n.Lhs {
975 if isName(p) && n != name.Defn {
976 return true
977 }
978 }
979 case OASOP:
980 n := n.(*AssignOpStmt)
981 if isName(n.X) {
982 return true
983 }
984 case OADDR:
985 n := n.(*AddrExpr)
986 if isName(n.X) {
987 base.FatalfAt(n.Pos(), "%v not marked addrtaken", name)
988 }
989 case ORANGE:
990 n := n.(*RangeStmt)
991 if isName(n.Key) || isName(n.Value) {
992 return true
993 }
994 case OCLOSURE:
995 n := n.(*ClosureExpr)
996 if Any(n.Func, do) {
997 return true
998 }
999 }
1000 return false
1001 }
1002 return Any(name.Curfn, do)
1003 }
1004
1005
1006 func StaticCalleeName(n Node) *Name {
1007 switch n.Op() {
1008 case OMETHEXPR:
1009 n := n.(*SelectorExpr)
1010 return MethodExprName(n)
1011 case ONAME:
1012 n := n.(*Name)
1013 if n.Class == PFUNC {
1014 return n
1015 }
1016 case OCLOSURE:
1017 return n.(*ClosureExpr).Func.Nname
1018 }
1019 return nil
1020 }
1021
1022
1023 var IsIntrinsicCall = func(*CallExpr) bool { return false }
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040 func SameSafeExpr(l Node, r Node) bool {
1041 for l.Op() == OCONVNOP {
1042 l = l.(*ConvExpr).X
1043 }
1044 for r.Op() == OCONVNOP {
1045 r = r.(*ConvExpr).X
1046 }
1047 if l.Op() != r.Op() || !types.Identical(l.Type(), r.Type()) {
1048 return false
1049 }
1050
1051 switch l.Op() {
1052 case ONAME:
1053 return l == r
1054
1055 case ODOT, ODOTPTR:
1056 l := l.(*SelectorExpr)
1057 r := r.(*SelectorExpr)
1058 return l.Sel != nil && r.Sel != nil && l.Sel == r.Sel && SameSafeExpr(l.X, r.X)
1059
1060 case ODEREF:
1061 l := l.(*StarExpr)
1062 r := r.(*StarExpr)
1063 return SameSafeExpr(l.X, r.X)
1064
1065 case ONOT, OBITNOT, OPLUS, ONEG:
1066 l := l.(*UnaryExpr)
1067 r := r.(*UnaryExpr)
1068 return SameSafeExpr(l.X, r.X)
1069
1070 case OCONV:
1071 l := l.(*ConvExpr)
1072 r := r.(*ConvExpr)
1073
1074
1075 return types.IsSimple[l.Type().Kind()] && SameSafeExpr(l.X, r.X)
1076
1077 case OINDEX, OINDEXMAP:
1078 l := l.(*IndexExpr)
1079 r := r.(*IndexExpr)
1080 return SameSafeExpr(l.X, r.X) && SameSafeExpr(l.Index, r.Index)
1081
1082 case OADD, OSUB, OOR, OXOR, OMUL, OLSH, ORSH, OAND, OANDNOT, ODIV, OMOD:
1083 l := l.(*BinaryExpr)
1084 r := r.(*BinaryExpr)
1085 return SameSafeExpr(l.X, r.X) && SameSafeExpr(l.Y, r.Y)
1086
1087 case OLITERAL:
1088 return constant.Compare(l.Val(), token.EQL, r.Val())
1089
1090 case ONIL:
1091 return true
1092 }
1093
1094 return false
1095 }
1096
1097
1098
1099
1100 func ShouldCheckPtr(fn *Func, level int) bool {
1101 return base.Debug.Checkptr >= level && fn.Pragma&NoCheckPtr == 0
1102 }
1103
1104
1105
1106 func ShouldAsanCheckPtr(fn *Func) bool {
1107 return base.Flag.ASan && fn.Pragma&NoCheckPtr == 0
1108 }
1109
1110
1111
1112 func IsReflectHeaderDataField(l Node) bool {
1113 if l.Type() != types.Types[types.TUINTPTR] {
1114 return false
1115 }
1116
1117 var tsym *types.Sym
1118 switch l.Op() {
1119 case ODOT:
1120 l := l.(*SelectorExpr)
1121 tsym = l.X.Type().Sym()
1122 case ODOTPTR:
1123 l := l.(*SelectorExpr)
1124 tsym = l.X.Type().Elem().Sym()
1125 default:
1126 return false
1127 }
1128
1129 if tsym == nil || l.Sym().Name != "Data" || tsym.Pkg.Path != "reflect" {
1130 return false
1131 }
1132 return tsym.Name == "SliceHeader" || tsym.Name == "StringHeader"
1133 }
1134
1135 func ParamNames(ft *types.Type) []Node {
1136 args := make([]Node, ft.NumParams())
1137 for i, f := range ft.Params() {
1138 args[i] = f.Nname.(*Name)
1139 }
1140 return args
1141 }
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151 func MethodSym(recv *types.Type, msym *types.Sym) *types.Sym {
1152 sym := MethodSymSuffix(recv, msym, "")
1153 sym.SetFunc(true)
1154 return sym
1155 }
1156
1157
1158
1159
1160 func MethodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sym {
1161 if msym.IsBlank() {
1162 base.Fatalf("blank method name")
1163 }
1164
1165 rsym := recv.Sym()
1166 if recv.IsPtr() {
1167 if rsym != nil {
1168 base.Fatalf("declared pointer receiver type: %v", recv)
1169 }
1170 rsym = recv.Elem().Sym()
1171 }
1172
1173
1174
1175
1176 rpkg := Pkgs.Go
1177 if rsym != nil {
1178 rpkg = rsym.Pkg
1179 }
1180
1181 var b bytes.Buffer
1182 if recv.IsPtr() {
1183
1184
1185 fmt.Fprintf(&b, "(%-S)", recv)
1186 } else {
1187 fmt.Fprintf(&b, "%-S", recv)
1188 }
1189
1190
1191
1192
1193
1194 if !types.IsExported(msym.Name) && msym.Pkg != rpkg {
1195 b.WriteString(".")
1196 b.WriteString(msym.Pkg.Prefix)
1197 }
1198
1199 b.WriteString(".")
1200 b.WriteString(msym.Name)
1201 b.WriteString(suffix)
1202 return rpkg.LookupBytes(b.Bytes())
1203 }
1204
1205
1206
1207
1208
1209 func LookupMethodSelector(pkg *types.Pkg, name string) (typ, meth *types.Sym, err error) {
1210 typeName, methName := splitType(name)
1211 if typeName == "" {
1212 return nil, nil, fmt.Errorf("%s doesn't contain type split", name)
1213 }
1214
1215 if len(typeName) > 3 && typeName[:2] == "(*" && typeName[len(typeName)-1] == ')' {
1216
1217
1218 typeName = typeName[2 : len(typeName)-1]
1219 }
1220
1221 typ = pkg.Lookup(typeName)
1222 meth = pkg.Selector(methName)
1223 return typ, meth, nil
1224 }
1225
1226
1227
1228
1229
1230
1231 func splitType(name string) (typ, fn string) {
1232
1233
1234
1235 bracket := 0
1236 for i, r := range name {
1237 if r == '.' && bracket == 0 {
1238 return name[:i], name[i+1:]
1239 }
1240 if r == '[' {
1241 bracket++
1242 }
1243 if r == ']' {
1244 bracket--
1245 }
1246 }
1247 return "", name
1248 }
1249
1250
1251
1252
1253 func MethodExprName(n Node) *Name {
1254 name, _ := MethodExprFunc(n).Nname.(*Name)
1255 return name
1256 }
1257
1258
1259 func MethodExprFunc(n Node) *types.Field {
1260 switch n.Op() {
1261 case ODOTMETH, OMETHEXPR, OMETHVALUE:
1262 return n.(*SelectorExpr).Selection
1263 }
1264 base.Fatalf("unexpected node: %v (%v)", n, n.Op())
1265 panic("unreachable")
1266 }
1267
View as plain text