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