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