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 typ *types.Type
31 init Nodes
32 flags bitset8
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, OGETCALLERPC, 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 func StaticValue(n Node) Node {
858 for {
859 switch n1 := n.(type) {
860 case *ConvExpr:
861 if n1.Op() == OCONVNOP {
862 n = n1.X
863 continue
864 }
865 case *InlinedCallExpr:
866 if n1.Op() == OINLCALL {
867 n = n1.SingleResult()
868 continue
869 }
870 case *ParenExpr:
871 n = n1.X
872 continue
873 }
874
875 n1 := staticValue1(n)
876 if n1 == nil {
877 return n
878 }
879 n = n1
880 }
881 }
882
883 func staticValue1(nn Node) Node {
884 if nn.Op() != ONAME {
885 return nil
886 }
887 n := nn.(*Name).Canonical()
888 if n.Class != PAUTO {
889 return nil
890 }
891
892 defn := n.Defn
893 if defn == nil {
894 return nil
895 }
896
897 var rhs Node
898 FindRHS:
899 switch defn.Op() {
900 case OAS:
901 defn := defn.(*AssignStmt)
902 rhs = defn.Y
903 case OAS2:
904 defn := defn.(*AssignListStmt)
905 for i, lhs := range defn.Lhs {
906 if lhs == n {
907 rhs = defn.Rhs[i]
908 break FindRHS
909 }
910 }
911 base.Fatalf("%v missing from LHS of %v", n, defn)
912 default:
913 return nil
914 }
915 if rhs == nil {
916 base.Fatalf("RHS is nil: %v", defn)
917 }
918
919 if Reassigned(n) {
920 return nil
921 }
922
923 return rhs
924 }
925
926
927
928
929
930
931
932
933
934 func Reassigned(name *Name) bool {
935 if name.Op() != ONAME {
936 base.Fatalf("reassigned %v", name)
937 }
938
939 if name.Curfn == nil {
940 return true
941 }
942
943 if name.Addrtaken() {
944 return true
945 }
946
947
948
949
950
951
952 isName := func(x Node) bool {
953 if x == nil {
954 return false
955 }
956 n, ok := OuterValue(x).(*Name)
957 return ok && n.Canonical() == name
958 }
959
960 var do func(n Node) bool
961 do = func(n Node) bool {
962 switch n.Op() {
963 case OAS:
964 n := n.(*AssignStmt)
965 if isName(n.X) && n != name.Defn {
966 return true
967 }
968 case OAS2, OAS2FUNC, OAS2MAPR, OAS2DOTTYPE, OAS2RECV, OSELRECV2:
969 n := n.(*AssignListStmt)
970 for _, p := range n.Lhs {
971 if isName(p) && n != name.Defn {
972 return true
973 }
974 }
975 case OASOP:
976 n := n.(*AssignOpStmt)
977 if isName(n.X) {
978 return true
979 }
980 case OADDR:
981 n := n.(*AddrExpr)
982 if isName(n.X) {
983 base.FatalfAt(n.Pos(), "%v not marked addrtaken", name)
984 }
985 case ORANGE:
986 n := n.(*RangeStmt)
987 if isName(n.Key) || isName(n.Value) {
988 return true
989 }
990 case OCLOSURE:
991 n := n.(*ClosureExpr)
992 if Any(n.Func, do) {
993 return true
994 }
995 }
996 return false
997 }
998 return Any(name.Curfn, do)
999 }
1000
1001
1002 func StaticCalleeName(n Node) *Name {
1003 switch n.Op() {
1004 case OMETHEXPR:
1005 n := n.(*SelectorExpr)
1006 return MethodExprName(n)
1007 case ONAME:
1008 n := n.(*Name)
1009 if n.Class == PFUNC {
1010 return n
1011 }
1012 case OCLOSURE:
1013 return n.(*ClosureExpr).Func.Nname
1014 }
1015 return nil
1016 }
1017
1018
1019 var IsIntrinsicCall = func(*CallExpr) bool { return false }
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036 func SameSafeExpr(l Node, r Node) bool {
1037 for l.Op() == OCONVNOP {
1038 l = l.(*ConvExpr).X
1039 }
1040 for r.Op() == OCONVNOP {
1041 r = r.(*ConvExpr).X
1042 }
1043 if l.Op() != r.Op() || !types.Identical(l.Type(), r.Type()) {
1044 return false
1045 }
1046
1047 switch l.Op() {
1048 case ONAME:
1049 return l == r
1050
1051 case ODOT, ODOTPTR:
1052 l := l.(*SelectorExpr)
1053 r := r.(*SelectorExpr)
1054 return l.Sel != nil && r.Sel != nil && l.Sel == r.Sel && SameSafeExpr(l.X, r.X)
1055
1056 case ODEREF:
1057 l := l.(*StarExpr)
1058 r := r.(*StarExpr)
1059 return SameSafeExpr(l.X, r.X)
1060
1061 case ONOT, OBITNOT, OPLUS, ONEG:
1062 l := l.(*UnaryExpr)
1063 r := r.(*UnaryExpr)
1064 return SameSafeExpr(l.X, r.X)
1065
1066 case OCONV:
1067 l := l.(*ConvExpr)
1068 r := r.(*ConvExpr)
1069
1070
1071 return types.IsSimple[l.Type().Kind()] && SameSafeExpr(l.X, r.X)
1072
1073 case OINDEX, OINDEXMAP:
1074 l := l.(*IndexExpr)
1075 r := r.(*IndexExpr)
1076 return SameSafeExpr(l.X, r.X) && SameSafeExpr(l.Index, r.Index)
1077
1078 case OADD, OSUB, OOR, OXOR, OMUL, OLSH, ORSH, OAND, OANDNOT, ODIV, OMOD:
1079 l := l.(*BinaryExpr)
1080 r := r.(*BinaryExpr)
1081 return SameSafeExpr(l.X, r.X) && SameSafeExpr(l.Y, r.Y)
1082
1083 case OLITERAL:
1084 return constant.Compare(l.Val(), token.EQL, r.Val())
1085
1086 case ONIL:
1087 return true
1088 }
1089
1090 return false
1091 }
1092
1093
1094
1095
1096 func ShouldCheckPtr(fn *Func, level int) bool {
1097 return base.Debug.Checkptr >= level && fn.Pragma&NoCheckPtr == 0
1098 }
1099
1100
1101
1102 func ShouldAsanCheckPtr(fn *Func) bool {
1103 return base.Flag.ASan && fn.Pragma&NoCheckPtr == 0
1104 }
1105
1106
1107
1108 func IsReflectHeaderDataField(l Node) bool {
1109 if l.Type() != types.Types[types.TUINTPTR] {
1110 return false
1111 }
1112
1113 var tsym *types.Sym
1114 switch l.Op() {
1115 case ODOT:
1116 l := l.(*SelectorExpr)
1117 tsym = l.X.Type().Sym()
1118 case ODOTPTR:
1119 l := l.(*SelectorExpr)
1120 tsym = l.X.Type().Elem().Sym()
1121 default:
1122 return false
1123 }
1124
1125 if tsym == nil || l.Sym().Name != "Data" || tsym.Pkg.Path != "reflect" {
1126 return false
1127 }
1128 return tsym.Name == "SliceHeader" || tsym.Name == "StringHeader"
1129 }
1130
1131 func ParamNames(ft *types.Type) []Node {
1132 args := make([]Node, ft.NumParams())
1133 for i, f := range ft.Params() {
1134 args[i] = f.Nname.(*Name)
1135 }
1136 return args
1137 }
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147 func MethodSym(recv *types.Type, msym *types.Sym) *types.Sym {
1148 sym := MethodSymSuffix(recv, msym, "")
1149 sym.SetFunc(true)
1150 return sym
1151 }
1152
1153
1154
1155
1156 func MethodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sym {
1157 if msym.IsBlank() {
1158 base.Fatalf("blank method name")
1159 }
1160
1161 rsym := recv.Sym()
1162 if recv.IsPtr() {
1163 if rsym != nil {
1164 base.Fatalf("declared pointer receiver type: %v", recv)
1165 }
1166 rsym = recv.Elem().Sym()
1167 }
1168
1169
1170
1171
1172 rpkg := Pkgs.Go
1173 if rsym != nil {
1174 rpkg = rsym.Pkg
1175 }
1176
1177 var b bytes.Buffer
1178 if recv.IsPtr() {
1179
1180
1181 fmt.Fprintf(&b, "(%-S)", recv)
1182 } else {
1183 fmt.Fprintf(&b, "%-S", recv)
1184 }
1185
1186
1187
1188
1189
1190 if !types.IsExported(msym.Name) && msym.Pkg != rpkg {
1191 b.WriteString(".")
1192 b.WriteString(msym.Pkg.Prefix)
1193 }
1194
1195 b.WriteString(".")
1196 b.WriteString(msym.Name)
1197 b.WriteString(suffix)
1198 return rpkg.LookupBytes(b.Bytes())
1199 }
1200
1201
1202
1203
1204
1205 func LookupMethodSelector(pkg *types.Pkg, name string) (typ, meth *types.Sym, err error) {
1206 typeName, methName := splitType(name)
1207 if typeName == "" {
1208 return nil, nil, fmt.Errorf("%s doesn't contain type split", name)
1209 }
1210
1211 if len(typeName) > 3 && typeName[:2] == "(*" && typeName[len(typeName)-1] == ')' {
1212
1213
1214 typeName = typeName[2 : len(typeName)-1]
1215 }
1216
1217 typ = pkg.Lookup(typeName)
1218 meth = pkg.Selector(methName)
1219 return typ, meth, nil
1220 }
1221
1222
1223
1224
1225
1226
1227 func splitType(name string) (typ, fn string) {
1228
1229
1230
1231 bracket := 0
1232 for i, r := range name {
1233 if r == '.' && bracket == 0 {
1234 return name[:i], name[i+1:]
1235 }
1236 if r == '[' {
1237 bracket++
1238 }
1239 if r == ']' {
1240 bracket--
1241 }
1242 }
1243 return "", name
1244 }
1245
1246
1247
1248
1249 func MethodExprName(n Node) *Name {
1250 name, _ := MethodExprFunc(n).Nname.(*Name)
1251 return name
1252 }
1253
1254
1255 func MethodExprFunc(n Node) *types.Field {
1256 switch n.Op() {
1257 case ODOTMETH, OMETHEXPR, OMETHVALUE:
1258 return n.(*SelectorExpr).Selection
1259 }
1260 base.Fatalf("unexpected node: %v (%v)", n, n.Op())
1261 panic("unreachable")
1262 }
1263
View as plain text