1// Copyright 2020 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package ir
6
7import (
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// An Expr is a Node that can appear as an expression.
19type Expr interface {
20	Node
21	isExpr()
22}
23
24// A miniExpr is a miniNode with extra fields common to expressions.
25// TODO(rsc): Once we are sure about the contents, compact the bools
26// into a bit field and leave extra bits available for implementations
27// embedding miniExpr. Right now there are ~60 unused bits sitting here.
28type miniExpr struct {
29	miniNode
30	typ   *types.Type
31	init  Nodes // TODO(rsc): Don't require every Node to have an init
32	flags bitset8
33}
34
35const (
36	miniExprNonNil = 1 << iota
37	miniExprTransient
38	miniExprBounded
39	miniExprImplicit // for use by implementations; not supported by every Expr
40	miniExprCheckPtr
41)
42
43func (*miniExpr) isExpr() {}
44
45func (n *miniExpr) Type() *types.Type     { return n.typ }
46func (n *miniExpr) SetType(x *types.Type) { n.typ = x }
47func (n *miniExpr) NonNil() bool          { return n.flags&miniExprNonNil != 0 }
48func (n *miniExpr) MarkNonNil()           { n.flags |= miniExprNonNil }
49func (n *miniExpr) Transient() bool       { return n.flags&miniExprTransient != 0 }
50func (n *miniExpr) SetTransient(b bool)   { n.flags.set(miniExprTransient, b) }
51func (n *miniExpr) Bounded() bool         { return n.flags&miniExprBounded != 0 }
52func (n *miniExpr) SetBounded(b bool)     { n.flags.set(miniExprBounded, b) }
53func (n *miniExpr) Init() Nodes           { return n.init }
54func (n *miniExpr) PtrInit() *Nodes       { return &n.init }
55func (n *miniExpr) SetInit(x Nodes)       { n.init = x }
56
57// An AddStringExpr is a string concatenation Expr[0] + Exprs[1] + ... + Expr[len(Expr)-1].
58type AddStringExpr struct {
59	miniExpr
60	List     Nodes
61	Prealloc *Name
62}
63
64func 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// An AddrExpr is an address-of expression &X.
73// It may end up being a normal address-of or an allocation of a composite literal.
74type AddrExpr struct {
75	miniExpr
76	X        Node
77	Prealloc *Name // preallocated storage if any
78}
79
80func NewAddrExpr(pos src.XPos, x Node) *AddrExpr {
81	n := &AddrExpr{X: x}
82	n.op = OADDR
83	n.pos = pos
84	return n
85}
86
87func (n *AddrExpr) Implicit() bool     { return n.flags&miniExprImplicit != 0 }
88func (n *AddrExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
89
90func (n *AddrExpr) SetOp(op Op) {
91	switch op {
92	default:
93		panic(n.no("SetOp " + op.String()))
94	case OADDR, OPTRLIT:
95		n.op = op
96	}
97}
98
99// A BasicLit is a literal of basic type.
100type BasicLit struct {
101	miniExpr
102	val constant.Value
103}
104
105func NewBasicLit(pos src.XPos, val constant.Value) Node {
106	n := &BasicLit{val: val}
107	n.op = OLITERAL
108	n.pos = pos
109	if k := val.Kind(); k != constant.Unknown {
110		n.SetType(idealType(k))
111	}
112	return n
113}
114
115func (n *BasicLit) Val() constant.Value       { return n.val }
116func (n *BasicLit) SetVal(val constant.Value) { n.val = val }
117
118// A BinaryExpr is a binary expression X Op Y,
119// or Op(X, Y) for builtin functions that do not become calls.
120type BinaryExpr struct {
121	miniExpr
122	X Node
123	Y Node
124}
125
126func NewBinaryExpr(pos src.XPos, op Op, x, y Node) *BinaryExpr {
127	n := &BinaryExpr{X: x, Y: y}
128	n.pos = pos
129	n.SetOp(op)
130	return n
131}
132
133func (n *BinaryExpr) SetOp(op Op) {
134	switch op {
135	default:
136		panic(n.no("SetOp " + op.String()))
137	case OADD, OADDSTR, OAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE,
138		OLSH, OLT, OMOD, OMUL, ONE, OOR, ORSH, OSUB, OXOR,
139		OCOPY, OCOMPLEX, OUNSAFEADD, OUNSAFESLICE,
140		OEFACE:
141		n.op = op
142	}
143}
144
145// A CallExpr is a function call X(Args).
146type CallExpr struct {
147	miniExpr
148	origNode
149	X         Node
150	Args      Nodes
151	KeepAlive []*Name // vars to be kept alive until call returns
152	IsDDD     bool
153	NoInline  bool
154}
155
156func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr {
157	n := &CallExpr{X: fun}
158	n.pos = pos
159	n.orig = n
160	n.SetOp(op)
161	n.Args = args
162	return n
163}
164
165func (*CallExpr) isStmt() {}
166
167func (n *CallExpr) SetOp(op Op) {
168	switch op {
169	default:
170		panic(n.no("SetOp " + op.String()))
171	case OAPPEND,
172		OCALL, OCALLFUNC, OCALLINTER, OCALLMETH,
173		ODELETE,
174		OGETG, OGETCALLERPC, OGETCALLERSP,
175		OMAKE, OPRINT, OPRINTN,
176		ORECOVER, ORECOVERFP:
177		n.op = op
178	}
179}
180
181// A ClosureExpr is a function literal expression.
182type ClosureExpr struct {
183	miniExpr
184	Func     *Func `mknode:"-"`
185	Prealloc *Name
186	IsGoWrap bool // whether this is wrapper closure of a go statement
187}
188
189// Deprecated: Use NewClosureFunc instead.
190func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr {
191	n := &ClosureExpr{Func: fn}
192	n.op = OCLOSURE
193	n.pos = pos
194	return n
195}
196
197// A CompLitExpr is a composite literal Type{Vals}.
198// Before type-checking, the type is Ntype.
199type CompLitExpr struct {
200	miniExpr
201	origNode
202	Ntype    Ntype
203	List     Nodes // initialized values
204	Prealloc *Name
205	Len      int64 // backing array length for OSLICELIT
206}
207
208func NewCompLitExpr(pos src.XPos, op Op, typ Ntype, list []Node) *CompLitExpr {
209	n := &CompLitExpr{Ntype: typ}
210	n.pos = pos
211	n.SetOp(op)
212	n.List = list
213	n.orig = n
214	return n
215}
216
217func (n *CompLitExpr) Implicit() bool     { return n.flags&miniExprImplicit != 0 }
218func (n *CompLitExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
219
220func (n *CompLitExpr) SetOp(op Op) {
221	switch op {
222	default:
223		panic(n.no("SetOp " + op.String()))
224	case OARRAYLIT, OCOMPLIT, OMAPLIT, OSTRUCTLIT, OSLICELIT:
225		n.op = op
226	}
227}
228
229type ConstExpr struct {
230	miniExpr
231	origNode
232	val constant.Value
233}
234
235func NewConstExpr(val constant.Value, orig Node) Node {
236	n := &ConstExpr{val: val}
237	n.op = OLITERAL
238	n.pos = orig.Pos()
239	n.orig = orig
240	n.SetType(orig.Type())
241	n.SetTypecheck(orig.Typecheck())
242	n.SetDiag(orig.Diag())
243	return n
244}
245
246func (n *ConstExpr) Sym() *types.Sym     { return n.orig.Sym() }
247func (n *ConstExpr) Val() constant.Value { return n.val }
248
249// A ConvExpr is a conversion Type(X).
250// It may end up being a value or a type.
251type ConvExpr struct {
252	miniExpr
253	X Node
254}
255
256func NewConvExpr(pos src.XPos, op Op, typ *types.Type, x Node) *ConvExpr {
257	n := &ConvExpr{X: x}
258	n.pos = pos
259	n.typ = typ
260	n.SetOp(op)
261	return n
262}
263
264func (n *ConvExpr) Implicit() bool     { return n.flags&miniExprImplicit != 0 }
265func (n *ConvExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
266func (n *ConvExpr) CheckPtr() bool     { return n.flags&miniExprCheckPtr != 0 }
267func (n *ConvExpr) SetCheckPtr(b bool) { n.flags.set(miniExprCheckPtr, b) }
268
269func (n *ConvExpr) SetOp(op Op) {
270	switch op {
271	default:
272		panic(n.no("SetOp " + op.String()))
273	case OCONV, OCONVIFACE, OCONVIDATA, OCONVNOP, OBYTES2STR, OBYTES2STRTMP, ORUNES2STR, OSTR2BYTES, OSTR2BYTESTMP, OSTR2RUNES, ORUNESTR, OSLICE2ARRPTR:
274		n.op = op
275	}
276}
277
278// An IndexExpr is an index expression X[Index].
279type IndexExpr struct {
280	miniExpr
281	X        Node
282	Index    Node
283	Assigned bool
284}
285
286func NewIndexExpr(pos src.XPos, x, index Node) *IndexExpr {
287	n := &IndexExpr{X: x, Index: index}
288	n.pos = pos
289	n.op = OINDEX
290	return n
291}
292
293func (n *IndexExpr) SetOp(op Op) {
294	switch op {
295	default:
296		panic(n.no("SetOp " + op.String()))
297	case OINDEX, OINDEXMAP:
298		n.op = op
299	}
300}
301
302// A KeyExpr is a Key: Value composite literal key.
303type KeyExpr struct {
304	miniExpr
305	Key   Node
306	Value Node
307}
308
309func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr {
310	n := &KeyExpr{Key: key, Value: value}
311	n.pos = pos
312	n.op = OKEY
313	return n
314}
315
316// A StructKeyExpr is an Field: Value composite literal key.
317type StructKeyExpr struct {
318	miniExpr
319	Field *types.Field
320	Value Node
321}
322
323func NewStructKeyExpr(pos src.XPos, field *types.Field, value Node) *StructKeyExpr {
324	n := &StructKeyExpr{Field: field, Value: value}
325	n.pos = pos
326	n.op = OSTRUCTKEY
327	return n
328}
329
330func (n *StructKeyExpr) Sym() *types.Sym { return n.Field.Sym }
331
332// An InlinedCallExpr is an inlined function call.
333type InlinedCallExpr struct {
334	miniExpr
335	Body       Nodes
336	ReturnVars Nodes // must be side-effect free
337}
338
339func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr {
340	n := &InlinedCallExpr{}
341	n.pos = pos
342	n.op = OINLCALL
343	n.Body = body
344	n.ReturnVars = retvars
345	return n
346}
347
348func (n *InlinedCallExpr) SingleResult() Node {
349	if have := len(n.ReturnVars); have != 1 {
350		base.FatalfAt(n.Pos(), "inlined call has %v results, expected 1", have)
351	}
352	if !n.Type().HasShape() && n.ReturnVars[0].Type().HasShape() {
353		// If the type of the call is not a shape, but the type of the return value
354		// is a shape, we need to do an implicit conversion, so the real type
355		// of n is maintained.
356		r := NewConvExpr(n.Pos(), OCONVNOP, n.Type(), n.ReturnVars[0])
357		r.SetTypecheck(1)
358		return r
359	}
360	return n.ReturnVars[0]
361}
362
363// A LogicalExpr is a expression X Op Y where Op is && or ||.
364// It is separate from BinaryExpr to make room for statements
365// that must be executed before Y but after X.
366type LogicalExpr struct {
367	miniExpr
368	X Node
369	Y Node
370}
371
372func NewLogicalExpr(pos src.XPos, op Op, x, y Node) *LogicalExpr {
373	n := &LogicalExpr{X: x, Y: y}
374	n.pos = pos
375	n.SetOp(op)
376	return n
377}
378
379func (n *LogicalExpr) SetOp(op Op) {
380	switch op {
381	default:
382		panic(n.no("SetOp " + op.String()))
383	case OANDAND, OOROR:
384		n.op = op
385	}
386}
387
388// A MakeExpr is a make expression: make(Type[, Len[, Cap]]).
389// Op is OMAKECHAN, OMAKEMAP, OMAKESLICE, or OMAKESLICECOPY,
390// but *not* OMAKE (that's a pre-typechecking CallExpr).
391type MakeExpr struct {
392	miniExpr
393	Len Node
394	Cap Node
395}
396
397func NewMakeExpr(pos src.XPos, op Op, len, cap Node) *MakeExpr {
398	n := &MakeExpr{Len: len, Cap: cap}
399	n.pos = pos
400	n.SetOp(op)
401	return n
402}
403
404func (n *MakeExpr) SetOp(op Op) {
405	switch op {
406	default:
407		panic(n.no("SetOp " + op.String()))
408	case OMAKECHAN, OMAKEMAP, OMAKESLICE, OMAKESLICECOPY:
409		n.op = op
410	}
411}
412
413// A NilExpr represents the predefined untyped constant nil.
414// (It may be copied and assigned a type, though.)
415type NilExpr struct {
416	miniExpr
417	Sym_ *types.Sym // TODO: Remove
418}
419
420func NewNilExpr(pos src.XPos) *NilExpr {
421	n := &NilExpr{}
422	n.pos = pos
423	n.op = ONIL
424	return n
425}
426
427func (n *NilExpr) Sym() *types.Sym     { return n.Sym_ }
428func (n *NilExpr) SetSym(x *types.Sym) { n.Sym_ = x }
429
430// A ParenExpr is a parenthesized expression (X).
431// It may end up being a value or a type.
432type ParenExpr struct {
433	miniExpr
434	X Node
435}
436
437func NewParenExpr(pos src.XPos, x Node) *ParenExpr {
438	n := &ParenExpr{X: x}
439	n.op = OPAREN
440	n.pos = pos
441	return n
442}
443
444func (n *ParenExpr) Implicit() bool     { return n.flags&miniExprImplicit != 0 }
445func (n *ParenExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
446
447func (*ParenExpr) CanBeNtype() {}
448
449// SetOTYPE changes n to be an OTYPE node returning t,
450// like all the type nodes in type.go.
451func (n *ParenExpr) SetOTYPE(t *types.Type) {
452	n.op = OTYPE
453	n.typ = t
454	t.SetNod(n)
455}
456
457// A RawOrigExpr represents an arbitrary Go expression as a string value.
458// When printed in diagnostics, the string value is written out exactly as-is.
459type RawOrigExpr struct {
460	miniExpr
461	Raw string
462}
463
464func NewRawOrigExpr(pos src.XPos, op Op, raw string) *RawOrigExpr {
465	n := &RawOrigExpr{Raw: raw}
466	n.pos = pos
467	n.op = op
468	return n
469}
470
471// A ResultExpr represents a direct access to a result.
472type ResultExpr struct {
473	miniExpr
474	Index int64 // index of the result expr.
475}
476
477func NewResultExpr(pos src.XPos, typ *types.Type, index int64) *ResultExpr {
478	n := &ResultExpr{Index: index}
479	n.pos = pos
480	n.op = ORESULT
481	n.typ = typ
482	return n
483}
484
485// A LinksymOffsetExpr refers to an offset within a global variable.
486// It is like a SelectorExpr but without the field name.
487type LinksymOffsetExpr struct {
488	miniExpr
489	Linksym *obj.LSym
490	Offset_ int64
491}
492
493func NewLinksymOffsetExpr(pos src.XPos, lsym *obj.LSym, offset int64, typ *types.Type) *LinksymOffsetExpr {
494	n := &LinksymOffsetExpr{Linksym: lsym, Offset_: offset}
495	n.typ = typ
496	n.op = OLINKSYMOFFSET
497	return n
498}
499
500// NewLinksymExpr is NewLinksymOffsetExpr, but with offset fixed at 0.
501func NewLinksymExpr(pos src.XPos, lsym *obj.LSym, typ *types.Type) *LinksymOffsetExpr {
502	return NewLinksymOffsetExpr(pos, lsym, 0, typ)
503}
504
505// NewNameOffsetExpr is NewLinksymOffsetExpr, but taking a *Name
506// representing a global variable instead of an *obj.LSym directly.
507func NewNameOffsetExpr(pos src.XPos, name *Name, offset int64, typ *types.Type) *LinksymOffsetExpr {
508	if name == nil || IsBlank(name) || !(name.Op() == ONAME && name.Class == PEXTERN) {
509		base.FatalfAt(pos, "cannot take offset of nil, blank name or non-global variable: %v", name)
510	}
511	return NewLinksymOffsetExpr(pos, name.Linksym(), offset, typ)
512}
513
514// A SelectorExpr is a selector expression X.Sel.
515type SelectorExpr struct {
516	miniExpr
517	X Node
518	// Sel is the name of the field or method being selected, without (in the
519	// case of methods) any preceding type specifier. If the field/method is
520	// exported, than the Sym uses the local package regardless of the package
521	// of the containing type.
522	Sel *types.Sym
523	// The actual selected field - may not be filled in until typechecking.
524	Selection *types.Field
525	Prealloc  *Name // preallocated storage for OMETHVALUE, if any
526}
527
528func NewSelectorExpr(pos src.XPos, op Op, x Node, sel *types.Sym) *SelectorExpr {
529	n := &SelectorExpr{X: x, Sel: sel}
530	n.pos = pos
531	n.SetOp(op)
532	return n
533}
534
535func (n *SelectorExpr) SetOp(op Op) {
536	switch op {
537	default:
538		panic(n.no("SetOp " + op.String()))
539	case OXDOT, ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OMETHVALUE, OMETHEXPR:
540		n.op = op
541	}
542}
543
544func (n *SelectorExpr) Sym() *types.Sym    { return n.Sel }
545func (n *SelectorExpr) Implicit() bool     { return n.flags&miniExprImplicit != 0 }
546func (n *SelectorExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
547func (n *SelectorExpr) Offset() int64      { return n.Selection.Offset }
548
549func (n *SelectorExpr) FuncName() *Name {
550	if n.Op() != OMETHEXPR {
551		panic(n.no("FuncName"))
552	}
553	fn := NewNameAt(n.Selection.Pos, MethodSym(n.X.Type(), n.Sel))
554	fn.Class = PFUNC
555	fn.SetType(n.Type())
556	if n.Selection.Nname != nil {
557		// TODO(austin): Nname is nil for interface method
558		// expressions (I.M), so we can't attach a Func to
559		// those here. reflectdata.methodWrapper generates the
560		// Func.
561		fn.Func = n.Selection.Nname.(*Name).Func
562	}
563	return fn
564}
565
566// Before type-checking, bytes.Buffer is a SelectorExpr.
567// After type-checking it becomes a Name.
568func (*SelectorExpr) CanBeNtype() {}
569
570// A SliceExpr is a slice expression X[Low:High] or X[Low:High:Max].
571type SliceExpr struct {
572	miniExpr
573	X    Node
574	Low  Node
575	High Node
576	Max  Node
577}
578
579func NewSliceExpr(pos src.XPos, op Op, x, low, high, max Node) *SliceExpr {
580	n := &SliceExpr{X: x, Low: low, High: high, Max: max}
581	n.pos = pos
582	n.op = op
583	return n
584}
585
586func (n *SliceExpr) SetOp(op Op) {
587	switch op {
588	default:
589		panic(n.no("SetOp " + op.String()))
590	case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
591		n.op = op
592	}
593}
594
595// IsSlice3 reports whether o is a slice3 op (OSLICE3, OSLICE3ARR).
596// o must be a slicing op.
597func (o Op) IsSlice3() bool {
598	switch o {
599	case OSLICE, OSLICEARR, OSLICESTR:
600		return false
601	case OSLICE3, OSLICE3ARR:
602		return true
603	}
604	base.Fatalf("IsSlice3 op %v", o)
605	return false
606}
607
608// A SliceHeader expression constructs a slice header from its parts.
609type SliceHeaderExpr struct {
610	miniExpr
611	Ptr Node
612	Len Node
613	Cap Node
614}
615
616func NewSliceHeaderExpr(pos src.XPos, typ *types.Type, ptr, len, cap Node) *SliceHeaderExpr {
617	n := &SliceHeaderExpr{Ptr: ptr, Len: len, Cap: cap}
618	n.pos = pos
619	n.op = OSLICEHEADER
620	n.typ = typ
621	return n
622}
623
624// A StarExpr is a dereference expression *X.
625// It may end up being a value or a type.
626type StarExpr struct {
627	miniExpr
628	X Node
629}
630
631func NewStarExpr(pos src.XPos, x Node) *StarExpr {
632	n := &StarExpr{X: x}
633	n.op = ODEREF
634	n.pos = pos
635	return n
636}
637
638func (n *StarExpr) Implicit() bool     { return n.flags&miniExprImplicit != 0 }
639func (n *StarExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
640
641func (*StarExpr) CanBeNtype() {}
642
643// SetOTYPE changes n to be an OTYPE node returning t,
644// like all the type nodes in type.go.
645func (n *StarExpr) SetOTYPE(t *types.Type) {
646	n.op = OTYPE
647	n.X = nil
648	n.typ = t
649	t.SetNod(n)
650}
651
652// A TypeAssertionExpr is a selector expression X.(Type).
653// Before type-checking, the type is Ntype.
654type TypeAssertExpr struct {
655	miniExpr
656	X     Node
657	Ntype Ntype
658
659	// Runtime type information provided by walkDotType for
660	// assertions from non-empty interface to concrete type.
661	Itab *AddrExpr `mknode:"-"` // *runtime.itab for Type implementing X's type
662}
663
664func NewTypeAssertExpr(pos src.XPos, x Node, typ Ntype) *TypeAssertExpr {
665	n := &TypeAssertExpr{X: x, Ntype: typ}
666	n.pos = pos
667	n.op = ODOTTYPE
668	return n
669}
670
671func (n *TypeAssertExpr) SetOp(op Op) {
672	switch op {
673	default:
674		panic(n.no("SetOp " + op.String()))
675	case ODOTTYPE, ODOTTYPE2:
676		n.op = op
677	}
678}
679
680// A DynamicTypeAssertExpr asserts that X is of dynamic type T.
681type DynamicTypeAssertExpr struct {
682	miniExpr
683	X Node
684	// N = not an interface
685	// E = empty interface
686	// I = nonempty interface
687	// For E->N, T is a *runtime.type for N
688	// For I->N, T is a *runtime.itab for N+I
689	// For E->I, T is a *runtime.type for I
690	// For I->I, ditto
691	// For I->E, T is a *runtime.type for interface{} (unnecessary, but just to fill in the slot)
692	// For E->E, ditto
693	T Node
694}
695
696func NewDynamicTypeAssertExpr(pos src.XPos, op Op, x, t Node) *DynamicTypeAssertExpr {
697	n := &DynamicTypeAssertExpr{X: x, T: t}
698	n.pos = pos
699	n.op = op
700	return n
701}
702
703func (n *DynamicTypeAssertExpr) SetOp(op Op) {
704	switch op {
705	default:
706		panic(n.no("SetOp " + op.String()))
707	case ODYNAMICDOTTYPE, ODYNAMICDOTTYPE2:
708		n.op = op
709	}
710}
711
712// A UnaryExpr is a unary expression Op X,
713// or Op(X) for a builtin function that does not end up being a call.
714type UnaryExpr struct {
715	miniExpr
716	X Node
717}
718
719func NewUnaryExpr(pos src.XPos, op Op, x Node) *UnaryExpr {
720	n := &UnaryExpr{X: x}
721	n.pos = pos
722	n.SetOp(op)
723	return n
724}
725
726func (n *UnaryExpr) SetOp(op Op) {
727	switch op {
728	default:
729		panic(n.no("SetOp " + op.String()))
730	case OBITNOT, ONEG, ONOT, OPLUS, ORECV,
731		OALIGNOF, OCAP, OCLOSE, OIMAG, OLEN, ONEW,
732		OOFFSETOF, OPANIC, OREAL, OSIZEOF,
733		OCHECKNIL, OCFUNC, OIDATA, OITAB, OSPTR, OVARDEF, OVARKILL, OVARLIVE:
734		n.op = op
735	}
736}
737
738// Probably temporary: using Implicit() flag to mark generic function nodes that
739// are called to make getGfInfo analysis easier in one pre-order pass.
740func (n *InstExpr) Implicit() bool     { return n.flags&miniExprImplicit != 0 }
741func (n *InstExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
742
743// An InstExpr is a generic function or type instantiation.
744type InstExpr struct {
745	miniExpr
746	X     Node
747	Targs []Node
748}
749
750func NewInstExpr(pos src.XPos, op Op, x Node, targs []Node) *InstExpr {
751	n := &InstExpr{X: x, Targs: targs}
752	n.pos = pos
753	n.op = op
754	return n
755}
756
757func IsZero(n Node) bool {
758	switch n.Op() {
759	case ONIL:
760		return true
761
762	case OLITERAL:
763		switch u := n.Val(); u.Kind() {
764		case constant.String:
765			return constant.StringVal(u) == ""
766		case constant.Bool:
767			return !constant.BoolVal(u)
768		default:
769			return constant.Sign(u) == 0
770		}
771
772	case OARRAYLIT:
773		n := n.(*CompLitExpr)
774		for _, n1 := range n.List {
775			if n1.Op() == OKEY {
776				n1 = n1.(*KeyExpr).Value
777			}
778			if !IsZero(n1) {
779				return false
780			}
781		}
782		return true
783
784	case OSTRUCTLIT:
785		n := n.(*CompLitExpr)
786		for _, n1 := range n.List {
787			n1 := n1.(*StructKeyExpr)
788			if !IsZero(n1.Value) {
789				return false
790			}
791		}
792		return true
793	}
794
795	return false
796}
797
798// lvalue etc
799func IsAddressable(n Node) bool {
800	switch n.Op() {
801	case OINDEX:
802		n := n.(*IndexExpr)
803		if n.X.Type() != nil && n.X.Type().IsArray() {
804			return IsAddressable(n.X)
805		}
806		if n.X.Type() != nil && n.X.Type().IsString() {
807			return false
808		}
809		fallthrough
810	case ODEREF, ODOTPTR:
811		return true
812
813	case ODOT:
814		n := n.(*SelectorExpr)
815		return IsAddressable(n.X)
816
817	case ONAME:
818		n := n.(*Name)
819		if n.Class == PFUNC {
820			return false
821		}
822		return true
823
824	case OLINKSYMOFFSET:
825		return true
826	}
827
828	return false
829}
830
831func StaticValue(n Node) Node {
832	for {
833		if n.Op() == OCONVNOP {
834			n = n.(*ConvExpr).X
835			continue
836		}
837
838		if n.Op() == OINLCALL {
839			n = n.(*InlinedCallExpr).SingleResult()
840			continue
841		}
842
843		n1 := staticValue1(n)
844		if n1 == nil {
845			return n
846		}
847		n = n1
848	}
849}
850
851// staticValue1 implements a simple SSA-like optimization. If n is a local variable
852// that is initialized and never reassigned, staticValue1 returns the initializer
853// expression. Otherwise, it returns nil.
854func staticValue1(nn Node) Node {
855	if nn.Op() != ONAME {
856		return nil
857	}
858	n := nn.(*Name)
859	if n.Class != PAUTO {
860		return nil
861	}
862
863	defn := n.Defn
864	if defn == nil {
865		return nil
866	}
867
868	var rhs Node
869FindRHS:
870	switch defn.Op() {
871	case OAS:
872		defn := defn.(*AssignStmt)
873		rhs = defn.Y
874	case OAS2:
875		defn := defn.(*AssignListStmt)
876		for i, lhs := range defn.Lhs {
877			if lhs == n {
878				rhs = defn.Rhs[i]
879				break FindRHS
880			}
881		}
882		base.Fatalf("%v missing from LHS of %v", n, defn)
883	default:
884		return nil
885	}
886	if rhs == nil {
887		base.Fatalf("RHS is nil: %v", defn)
888	}
889
890	if reassigned(n) {
891		return nil
892	}
893
894	return rhs
895}
896
897// reassigned takes an ONAME node, walks the function in which it is defined, and returns a boolean
898// indicating whether the name has any assignments other than its declaration.
899// The second return value is the first such assignment encountered in the walk, if any. It is mostly
900// useful for -m output documenting the reason for inhibited optimizations.
901// NB: global variables are always considered to be re-assigned.
902// TODO: handle initial declaration not including an assignment and followed by a single assignment?
903func reassigned(name *Name) bool {
904	if name.Op() != ONAME {
905		base.Fatalf("reassigned %v", name)
906	}
907	// no way to reliably check for no-reassignment of globals, assume it can be
908	if name.Curfn == nil {
909		return true
910	}
911
912	// TODO(mdempsky): This is inefficient and becoming increasingly
913	// unwieldy. Figure out a way to generalize escape analysis's
914	// reassignment detection for use by inlining and devirtualization.
915
916	// isName reports whether n is a reference to name.
917	isName := func(x Node) bool {
918		n, ok := x.(*Name)
919		return ok && n.Canonical() == name
920	}
921
922	var do func(n Node) bool
923	do = func(n Node) bool {
924		switch n.Op() {
925		case OAS:
926			n := n.(*AssignStmt)
927			if isName(n.X) && n != name.Defn {
928				return true
929			}
930		case OAS2, OAS2FUNC, OAS2MAPR, OAS2DOTTYPE, OAS2RECV, OSELRECV2:
931			n := n.(*AssignListStmt)
932			for _, p := range n.Lhs {
933				if isName(p) && n != name.Defn {
934					return true
935				}
936			}
937		case OADDR:
938			n := n.(*AddrExpr)
939			if isName(OuterValue(n.X)) {
940				return true
941			}
942		case OCLOSURE:
943			n := n.(*ClosureExpr)
944			if Any(n.Func, do) {
945				return true
946			}
947		}
948		return false
949	}
950	return Any(name.Curfn, do)
951}
952
953// IsIntrinsicCall reports whether the compiler back end will treat the call as an intrinsic operation.
954var IsIntrinsicCall = func(*CallExpr) bool { return false }
955
956// SameSafeExpr checks whether it is safe to reuse one of l and r
957// instead of computing both. SameSafeExpr assumes that l and r are
958// used in the same statement or expression. In order for it to be
959// safe to reuse l or r, they must:
960// * be the same expression
961// * not have side-effects (no function calls, no channel ops);
962//   however, panics are ok
963// * not cause inappropriate aliasing; e.g. two string to []byte
964//   conversions, must result in two distinct slices
965//
966// The handling of OINDEXMAP is subtle. OINDEXMAP can occur both
967// as an lvalue (map assignment) and an rvalue (map access). This is
968// currently OK, since the only place SameSafeExpr gets used on an
969// lvalue expression is for OSLICE and OAPPEND optimizations, and it
970// is correct in those settings.
971func SameSafeExpr(l Node, r Node) bool {
972	if l.Op() != r.Op() || !types.Identical(l.Type(), r.Type()) {
973		return false
974	}
975
976	switch l.Op() {
977	case ONAME:
978		return l == r
979
980	case ODOT, ODOTPTR:
981		l := l.(*SelectorExpr)
982		r := r.(*SelectorExpr)
983		return l.Sel != nil && r.Sel != nil && l.Sel == r.Sel && SameSafeExpr(l.X, r.X)
984
985	case ODEREF:
986		l := l.(*StarExpr)
987		r := r.(*StarExpr)
988		return SameSafeExpr(l.X, r.X)
989
990	case ONOT, OBITNOT, OPLUS, ONEG:
991		l := l.(*UnaryExpr)
992		r := r.(*UnaryExpr)
993		return SameSafeExpr(l.X, r.X)
994
995	case OCONVNOP:
996		l := l.(*ConvExpr)
997		r := r.(*ConvExpr)
998		return SameSafeExpr(l.X, r.X)
999
1000	case OCONV:
1001		l := l.(*ConvExpr)
1002		r := r.(*ConvExpr)
1003		// Some conversions can't be reused, such as []byte(str).
1004		// Allow only numeric-ish types. This is a bit conservative.
1005		return types.IsSimple[l.Type().Kind()] && SameSafeExpr(l.X, r.X)
1006
1007	case OINDEX, OINDEXMAP:
1008		l := l.(*IndexExpr)
1009		r := r.(*IndexExpr)
1010		return SameSafeExpr(l.X, r.X) && SameSafeExpr(l.Index, r.Index)
1011
1012	case OADD, OSUB, OOR, OXOR, OMUL, OLSH, ORSH, OAND, OANDNOT, ODIV, OMOD:
1013		l := l.(*BinaryExpr)
1014		r := r.(*BinaryExpr)
1015		return SameSafeExpr(l.X, r.X) && SameSafeExpr(l.Y, r.Y)
1016
1017	case OLITERAL:
1018		return constant.Compare(l.Val(), token.EQL, r.Val())
1019
1020	case ONIL:
1021		return true
1022	}
1023
1024	return false
1025}
1026
1027// ShouldCheckPtr reports whether pointer checking should be enabled for
1028// function fn at a given level. See debugHelpFooter for defined
1029// levels.
1030func ShouldCheckPtr(fn *Func, level int) bool {
1031	return base.Debug.Checkptr >= level && fn.Pragma&NoCheckPtr == 0
1032}
1033
1034// IsReflectHeaderDataField reports whether l is an expression p.Data
1035// where p has type reflect.SliceHeader or reflect.StringHeader.
1036func IsReflectHeaderDataField(l Node) bool {
1037	if l.Type() != types.Types[types.TUINTPTR] {
1038		return false
1039	}
1040
1041	var tsym *types.Sym
1042	switch l.Op() {
1043	case ODOT:
1044		l := l.(*SelectorExpr)
1045		tsym = l.X.Type().Sym()
1046	case ODOTPTR:
1047		l := l.(*SelectorExpr)
1048		tsym = l.X.Type().Elem().Sym()
1049	default:
1050		return false
1051	}
1052
1053	if tsym == nil || l.Sym().Name != "Data" || tsym.Pkg.Path != "reflect" {
1054		return false
1055	}
1056	return tsym.Name == "SliceHeader" || tsym.Name == "StringHeader"
1057}
1058
1059func ParamNames(ft *types.Type) []Node {
1060	args := make([]Node, ft.NumParams())
1061	for i, f := range ft.Params().FieldSlice() {
1062		args[i] = AsNode(f.Nname)
1063	}
1064	return args
1065}
1066
1067// MethodSym returns the method symbol representing a method name
1068// associated with a specific receiver type.
1069//
1070// Method symbols can be used to distinguish the same method appearing
1071// in different method sets. For example, T.M and (*T).M have distinct
1072// method symbols.
1073//
1074// The returned symbol will be marked as a function.
1075func MethodSym(recv *types.Type, msym *types.Sym) *types.Sym {
1076	sym := MethodSymSuffix(recv, msym, "")
1077	sym.SetFunc(true)
1078	return sym
1079}
1080
1081// MethodSymSuffix is like methodsym, but allows attaching a
1082// distinguisher suffix. To avoid collisions, the suffix must not
1083// start with a letter, number, or period.
1084func MethodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sym {
1085	if msym.IsBlank() {
1086		base.Fatalf("blank method name")
1087	}
1088
1089	rsym := recv.Sym()
1090	if recv.IsPtr() {
1091		if rsym != nil {
1092			base.Fatalf("declared pointer receiver type: %v", recv)
1093		}
1094		rsym = recv.Elem().Sym()
1095	}
1096
1097	// Find the package the receiver type appeared in. For
1098	// anonymous receiver types (i.e., anonymous structs with
1099	// embedded fields), use the "go" pseudo-package instead.
1100	rpkg := Pkgs.Go
1101	if rsym != nil {
1102		rpkg = rsym.Pkg
1103	}
1104
1105	var b bytes.Buffer
1106	if recv.IsPtr() {
1107		// The parentheses aren't really necessary, but
1108		// they're pretty traditional at this point.
1109		fmt.Fprintf(&b, "(%-S)", recv)
1110	} else {
1111		fmt.Fprintf(&b, "%-S", recv)
1112	}
1113
1114	// A particular receiver type may have multiple non-exported
1115	// methods with the same name. To disambiguate them, include a
1116	// package qualifier for names that came from a different
1117	// package than the receiver type.
1118	if !types.IsExported(msym.Name) && msym.Pkg != rpkg {
1119		b.WriteString(".")
1120		b.WriteString(msym.Pkg.Prefix)
1121	}
1122
1123	b.WriteString(".")
1124	b.WriteString(msym.Name)
1125	b.WriteString(suffix)
1126
1127	return rpkg.LookupBytes(b.Bytes())
1128}
1129
1130// MethodExprName returns the ONAME representing the method
1131// referenced by expression n, which must be a method selector,
1132// method expression, or method value.
1133func MethodExprName(n Node) *Name {
1134	name, _ := MethodExprFunc(n).Nname.(*Name)
1135	return name
1136}
1137
1138// MethodExprFunc is like MethodExprName, but returns the types.Field instead.
1139func MethodExprFunc(n Node) *types.Field {
1140	switch n.Op() {
1141	case ODOTMETH, OMETHEXPR, OMETHVALUE:
1142		return n.(*SelectorExpr).Selection
1143	}
1144	base.Fatalf("unexpected node: %v (%v)", n, n.Op())
1145	panic("unreachable")
1146}
1147