1// Copyright 2009 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
5// “Abstract” syntax representation.
6
7package ir
8
9import (
10	"fmt"
11	"go/constant"
12	"sort"
13
14	"cmd/compile/internal/base"
15	"cmd/compile/internal/types"
16	"cmd/internal/src"
17)
18
19// A Node is the abstract interface to an IR node.
20type Node interface {
21	// Formatting
22	Format(s fmt.State, verb rune)
23
24	// Source position.
25	Pos() src.XPos
26	SetPos(x src.XPos)
27
28	// For making copies. For Copy and SepCopy.
29	copy() Node
30
31	doChildren(func(Node) bool) bool
32	editChildren(func(Node) Node)
33	editChildrenWithHidden(func(Node) Node)
34
35	// Abstract graph structure, for generic traversals.
36	Op() Op
37	Init() Nodes
38
39	// Fields specific to certain Ops only.
40	Type() *types.Type
41	SetType(t *types.Type)
42	Name() *Name
43	Sym() *types.Sym
44	Val() constant.Value
45	SetVal(v constant.Value)
46
47	// Storage for analysis passes.
48	Esc() uint16
49	SetEsc(x uint16)
50
51	// Typecheck values:
52	//  0 means the node is not typechecked
53	//  1 means the node is completely typechecked
54	//  2 means typechecking of the node is in progress
55	Typecheck() uint8
56	SetTypecheck(x uint8)
57	NonNil() bool
58	MarkNonNil()
59}
60
61// Line returns n's position as a string. If n has been inlined,
62// it uses the outermost position where n has been inlined.
63func Line(n Node) string {
64	return base.FmtPos(n.Pos())
65}
66
67func IsSynthetic(n Node) bool {
68	name := n.Sym().Name
69	return name[0] == '.' || name[0] == '~'
70}
71
72// IsAutoTmp indicates if n was created by the compiler as a temporary,
73// based on the setting of the .AutoTemp flag in n's Name.
74func IsAutoTmp(n Node) bool {
75	if n == nil || n.Op() != ONAME {
76		return false
77	}
78	return n.Name().AutoTemp()
79}
80
81// MayBeShared reports whether n may occur in multiple places in the AST.
82// Extra care must be taken when mutating such a node.
83func MayBeShared(n Node) bool {
84	switch n.Op() {
85	case ONAME, OLITERAL, ONIL, OTYPE:
86		return true
87	}
88	return false
89}
90
91type InitNode interface {
92	Node
93	PtrInit() *Nodes
94	SetInit(x Nodes)
95}
96
97func TakeInit(n Node) Nodes {
98	init := n.Init()
99	if len(init) != 0 {
100		n.(InitNode).SetInit(nil)
101	}
102	return init
103}
104
105//go:generate stringer -type=Op -trimprefix=O node.go
106
107type Op uint8
108
109// Node ops.
110const (
111	OXXX Op = iota
112
113	// names
114	ONAME // var or func name
115	// Unnamed arg or return value: f(int, string) (int, error) { etc }
116	// Also used for a qualified package identifier that hasn't been resolved yet.
117	ONONAME
118	OTYPE    // type name
119	OLITERAL // literal
120	ONIL     // nil
121
122	// expressions
123	OADD          // X + Y
124	OSUB          // X - Y
125	OOR           // X | Y
126	OXOR          // X ^ Y
127	OADDSTR       // +{List} (string addition, list elements are strings)
128	OADDR         // &X
129	OANDAND       // X && Y
130	OAPPEND       // append(Args); after walk, X may contain elem type descriptor
131	OBYTES2STR    // Type(X) (Type is string, X is a []byte)
132	OBYTES2STRTMP // Type(X) (Type is string, X is a []byte, ephemeral)
133	ORUNES2STR    // Type(X) (Type is string, X is a []rune)
134	OSTR2BYTES    // Type(X) (Type is []byte, X is a string)
135	OSTR2BYTESTMP // Type(X) (Type is []byte, X is a string, ephemeral)
136	OSTR2RUNES    // Type(X) (Type is []rune, X is a string)
137	OSLICE2ARR    // Type(X) (Type is [N]T, X is a []T)
138	OSLICE2ARRPTR // Type(X) (Type is *[N]T, X is a []T)
139	// X = Y or (if Def=true) X := Y
140	// If Def, then Init includes a DCL node for X.
141	OAS
142	// Lhs = Rhs (x, y, z = a, b, c) or (if Def=true) Lhs := Rhs
143	// If Def, then Init includes DCL nodes for Lhs
144	OAS2
145	OAS2DOTTYPE // Lhs = Rhs (x, ok = I.(int))
146	OAS2FUNC    // Lhs = Rhs (x, y = f())
147	OAS2MAPR    // Lhs = Rhs (x, ok = m["foo"])
148	OAS2RECV    // Lhs = Rhs (x, ok = <-c)
149	OASOP       // X AsOp= Y (x += y)
150	OCALL       // X(Args) (function call, method call or type conversion)
151
152	// OCALLFUNC, OCALLMETH, and OCALLINTER have the same structure.
153	// Prior to walk, they are: X(Args), where Args is all regular arguments.
154	// After walk, if any argument whose evaluation might requires temporary variable,
155	// that temporary variable will be pushed to Init, Args will contain an updated
156	// set of arguments.
157	OCALLFUNC  // X(Args) (function call f(args))
158	OCALLMETH  // X(Args) (direct method call x.Method(args))
159	OCALLINTER // X(Args) (interface method call x.Method(args))
160	OCAP       // cap(X)
161	OCLEAR     // clear(X)
162	OCLOSE     // close(X)
163	OCLOSURE   // func Type { Func.Closure.Body } (func literal)
164	OCOMPLIT   // Type{List} (composite literal, not yet lowered to specific form)
165	OMAPLIT    // Type{List} (composite literal, Type is map)
166	OSTRUCTLIT // Type{List} (composite literal, Type is struct)
167	OARRAYLIT  // Type{List} (composite literal, Type is array)
168	OSLICELIT  // Type{List} (composite literal, Type is slice), Len is slice length.
169	OPTRLIT    // &X (X is composite literal)
170	OCONV      // Type(X) (type conversion)
171	OCONVIFACE // Type(X) (type conversion, to interface)
172	OCONVNOP   // Type(X) (type conversion, no effect)
173	OCOPY      // copy(X, Y)
174	ODCL       // var X (declares X of type X.Type)
175
176	// Used during parsing but don't last.
177	ODCLFUNC // func f() or func (r) f()
178
179	ODELETE        // delete(Args)
180	ODOT           // X.Sel (X is of struct type)
181	ODOTPTR        // X.Sel (X is of pointer to struct type)
182	ODOTMETH       // X.Sel (X is non-interface, Sel is method name)
183	ODOTINTER      // X.Sel (X is interface, Sel is method name)
184	OXDOT          // X.Sel (before rewrite to one of the preceding)
185	ODOTTYPE       // X.Ntype or X.Type (.Ntype during parsing, .Type once resolved); after walk, Itab contains address of interface type descriptor and Itab.X contains address of concrete type descriptor
186	ODOTTYPE2      // X.Ntype or X.Type (.Ntype during parsing, .Type once resolved; on rhs of OAS2DOTTYPE); after walk, Itab contains address of interface type descriptor
187	OEQ            // X == Y
188	ONE            // X != Y
189	OLT            // X < Y
190	OLE            // X <= Y
191	OGE            // X >= Y
192	OGT            // X > Y
193	ODEREF         // *X
194	OINDEX         // X[Index] (index of array or slice)
195	OINDEXMAP      // X[Index] (index of map)
196	OKEY           // Key:Value (key:value in struct/array/map literal)
197	OSTRUCTKEY     // Field:Value (key:value in struct literal, after type checking)
198	OLEN           // len(X)
199	OMAKE          // make(Args) (before type checking converts to one of the following)
200	OMAKECHAN      // make(Type[, Len]) (type is chan)
201	OMAKEMAP       // make(Type[, Len]) (type is map)
202	OMAKESLICE     // make(Type[, Len[, Cap]]) (type is slice)
203	OMAKESLICECOPY // makeslicecopy(Type, Len, Cap) (type is slice; Len is length and Cap is the copied from slice)
204	// OMAKESLICECOPY is created by the order pass and corresponds to:
205	//  s = make(Type, Len); copy(s, Cap)
206	//
207	// Bounded can be set on the node when Len == len(Cap) is known at compile time.
208	//
209	// This node is created so the walk pass can optimize this pattern which would
210	// otherwise be hard to detect after the order pass.
211	OMUL              // X * Y
212	ODIV              // X / Y
213	OMOD              // X % Y
214	OLSH              // X << Y
215	ORSH              // X >> Y
216	OAND              // X & Y
217	OANDNOT           // X &^ Y
218	ONEW              // new(X); corresponds to calls to new in source code
219	ONOT              // !X
220	OBITNOT           // ^X
221	OPLUS             // +X
222	ONEG              // -X
223	OOROR             // X || Y
224	OPANIC            // panic(X)
225	OPRINT            // print(List)
226	OPRINTLN          // println(List)
227	OPAREN            // (X)
228	OSEND             // Chan <- Value
229	OSLICE            // X[Low : High] (X is untypechecked or slice)
230	OSLICEARR         // X[Low : High] (X is pointer to array)
231	OSLICESTR         // X[Low : High] (X is string)
232	OSLICE3           // X[Low : High : Max] (X is untypedchecked or slice)
233	OSLICE3ARR        // X[Low : High : Max] (X is pointer to array)
234	OSLICEHEADER      // sliceheader{Ptr, Len, Cap} (Ptr is unsafe.Pointer, Len is length, Cap is capacity)
235	OSTRINGHEADER     // stringheader{Ptr, Len} (Ptr is unsafe.Pointer, Len is length)
236	ORECOVER          // recover()
237	ORECOVERFP        // recover(Args) w/ explicit FP argument
238	ORECV             // <-X
239	ORUNESTR          // Type(X) (Type is string, X is rune)
240	OSELRECV2         // like OAS2: Lhs = Rhs where len(Lhs)=2, len(Rhs)=1, Rhs[0].Op = ORECV (appears as .Var of OCASE)
241	OMIN              // min(List)
242	OMAX              // max(List)
243	OREAL             // real(X)
244	OIMAG             // imag(X)
245	OCOMPLEX          // complex(X, Y)
246	OUNSAFEADD        // unsafe.Add(X, Y)
247	OUNSAFESLICE      // unsafe.Slice(X, Y)
248	OUNSAFESLICEDATA  // unsafe.SliceData(X)
249	OUNSAFESTRING     // unsafe.String(X, Y)
250	OUNSAFESTRINGDATA // unsafe.StringData(X)
251	OMETHEXPR         // X(Args) (method expression T.Method(args), first argument is the method receiver)
252	OMETHVALUE        // X.Sel   (method expression t.Method, not called)
253
254	// statements
255	OBLOCK // { List } (block of code)
256	OBREAK // break [Label]
257	// OCASE:  case List: Body (List==nil means default)
258	//   For OTYPESW, List is a OTYPE node for the specified type (or OLITERAL
259	//   for nil) or an ODYNAMICTYPE indicating a runtime type for generics.
260	//   If a type-switch variable is specified, Var is an
261	//   ONAME for the version of the type-switch variable with the specified
262	//   type.
263	OCASE
264	OCONTINUE // continue [Label]
265	ODEFER    // defer Call
266	OFALL     // fallthrough
267	OFOR      // for Init; Cond; Post { Body }
268	OGOTO     // goto Label
269	OIF       // if Init; Cond { Then } else { Else }
270	OLABEL    // Label:
271	OGO       // go Call
272	ORANGE    // for Key, Value = range X { Body }
273	ORETURN   // return Results
274	OSELECT   // select { Cases }
275	OSWITCH   // switch Init; Expr { Cases }
276	// OTYPESW:  X := Y.(type) (appears as .Tag of OSWITCH)
277	//   X is nil if there is no type-switch variable
278	OTYPESW
279
280	// misc
281	// intermediate representation of an inlined call.  Uses Init (assignments
282	// for the captured variables, parameters, retvars, & INLMARK op),
283	// Body (body of the inlined function), and ReturnVars (list of
284	// return values)
285	OINLCALL         // intermediary representation of an inlined call.
286	OMAKEFACE        // construct an interface value from rtype/itab and data pointers
287	OITAB            // rtype/itab pointer of an interface value
288	OIDATA           // data pointer of an interface value
289	OSPTR            // base pointer of a slice or string. Bounded==1 means known non-nil.
290	OCFUNC           // reference to c function pointer (not go func value)
291	OCHECKNIL        // emit code to ensure pointer/interface not nil
292	ORESULT          // result of a function call; Xoffset is stack offset
293	OINLMARK         // start of an inlined body, with file/line of caller. Xoffset is an index into the inline tree.
294	OLINKSYMOFFSET   // offset within a name
295	OJUMPTABLE       // A jump table structure for implementing dense expression switches
296	OINTERFACESWITCH // A type switch with interface cases
297
298	// opcodes for generics
299	ODYNAMICDOTTYPE  // x = i.(T) where T is a type parameter (or derived from a type parameter)
300	ODYNAMICDOTTYPE2 // x, ok = i.(T) where T is a type parameter (or derived from a type parameter)
301	ODYNAMICTYPE     // a type node for type switches (represents a dynamic target type for a type switch)
302
303	// arch-specific opcodes
304	OTAILCALL    // tail call to another function
305	OGETG        // runtime.getg() (read g pointer)
306	OGETCALLERPC // runtime.getcallerpc() (continuation PC in caller frame)
307	OGETCALLERSP // runtime.getcallersp() (stack pointer in caller frame)
308
309	OEND
310)
311
312// IsCmp reports whether op is a comparison operation (==, !=, <, <=,
313// >, or >=).
314func (op Op) IsCmp() bool {
315	switch op {
316	case OEQ, ONE, OLT, OLE, OGT, OGE:
317		return true
318	}
319	return false
320}
321
322// Nodes is a slice of Node.
323type Nodes []Node
324
325// ToNodes returns s as a slice of Nodes.
326func ToNodes[T Node](s []T) Nodes {
327	res := make(Nodes, len(s))
328	for i, n := range s {
329		res[i] = n
330	}
331	return res
332}
333
334// Append appends entries to Nodes.
335func (n *Nodes) Append(a ...Node) {
336	if len(a) == 0 {
337		return
338	}
339	*n = append(*n, a...)
340}
341
342// Prepend prepends entries to Nodes.
343// If a slice is passed in, this will take ownership of it.
344func (n *Nodes) Prepend(a ...Node) {
345	if len(a) == 0 {
346		return
347	}
348	*n = append(a, *n...)
349}
350
351// Take clears n, returning its former contents.
352func (n *Nodes) Take() []Node {
353	ret := *n
354	*n = nil
355	return ret
356}
357
358// Copy returns a copy of the content of the slice.
359func (n Nodes) Copy() Nodes {
360	if n == nil {
361		return nil
362	}
363	c := make(Nodes, len(n))
364	copy(c, n)
365	return c
366}
367
368// NameQueue is a FIFO queue of *Name. The zero value of NameQueue is
369// a ready-to-use empty queue.
370type NameQueue struct {
371	ring       []*Name
372	head, tail int
373}
374
375// Empty reports whether q contains no Names.
376func (q *NameQueue) Empty() bool {
377	return q.head == q.tail
378}
379
380// PushRight appends n to the right of the queue.
381func (q *NameQueue) PushRight(n *Name) {
382	if len(q.ring) == 0 {
383		q.ring = make([]*Name, 16)
384	} else if q.head+len(q.ring) == q.tail {
385		// Grow the ring.
386		nring := make([]*Name, len(q.ring)*2)
387		// Copy the old elements.
388		part := q.ring[q.head%len(q.ring):]
389		if q.tail-q.head <= len(part) {
390			part = part[:q.tail-q.head]
391			copy(nring, part)
392		} else {
393			pos := copy(nring, part)
394			copy(nring[pos:], q.ring[:q.tail%len(q.ring)])
395		}
396		q.ring, q.head, q.tail = nring, 0, q.tail-q.head
397	}
398
399	q.ring[q.tail%len(q.ring)] = n
400	q.tail++
401}
402
403// PopLeft pops a Name from the left of the queue. It panics if q is
404// empty.
405func (q *NameQueue) PopLeft() *Name {
406	if q.Empty() {
407		panic("dequeue empty")
408	}
409	n := q.ring[q.head%len(q.ring)]
410	q.head++
411	return n
412}
413
414// NameSet is a set of Names.
415type NameSet map[*Name]struct{}
416
417// Has reports whether s contains n.
418func (s NameSet) Has(n *Name) bool {
419	_, isPresent := s[n]
420	return isPresent
421}
422
423// Add adds n to s.
424func (s *NameSet) Add(n *Name) {
425	if *s == nil {
426		*s = make(map[*Name]struct{})
427	}
428	(*s)[n] = struct{}{}
429}
430
431// Sorted returns s sorted according to less.
432func (s NameSet) Sorted(less func(*Name, *Name) bool) []*Name {
433	var res []*Name
434	for n := range s {
435		res = append(res, n)
436	}
437	sort.Slice(res, func(i, j int) bool { return less(res[i], res[j]) })
438	return res
439}
440
441type PragmaFlag uint16
442
443const (
444	// Func pragmas.
445	Nointerface      PragmaFlag = 1 << iota
446	Noescape                    // func parameters don't escape
447	Norace                      // func must not have race detector annotations
448	Nosplit                     // func should not execute on separate stack
449	Noinline                    // func should not be inlined
450	NoCheckPtr                  // func should not be instrumented by checkptr
451	CgoUnsafeArgs               // treat a pointer to one arg as a pointer to them all
452	UintptrKeepAlive            // pointers converted to uintptr must be kept alive
453	UintptrEscapes              // pointers converted to uintptr escape
454
455	// Runtime-only func pragmas.
456	// See ../../../../runtime/HACKING.md for detailed descriptions.
457	Systemstack        // func must run on system stack
458	Nowritebarrier     // emit compiler error instead of write barrier
459	Nowritebarrierrec  // error on write barrier in this or recursive callees
460	Yeswritebarrierrec // cancels Nowritebarrierrec in this function and callees
461
462	// Go command pragmas
463	GoBuildPragma
464
465	RegisterParams // TODO(register args) remove after register abi is working
466
467)
468
469var BlankNode *Name
470
471func IsConst(n Node, ct constant.Kind) bool {
472	return ConstType(n) == ct
473}
474
475// IsNil reports whether n represents the universal untyped zero value "nil".
476func IsNil(n Node) bool {
477	return n != nil && n.Op() == ONIL
478}
479
480func IsBlank(n Node) bool {
481	if n == nil {
482		return false
483	}
484	return n.Sym().IsBlank()
485}
486
487// IsMethod reports whether n is a method.
488// n must be a function or a method.
489func IsMethod(n Node) bool {
490	return n.Type().Recv() != nil
491}
492
493// HasUniquePos reports whether n has a unique position that can be
494// used for reporting error messages.
495//
496// It's primarily used to distinguish references to named objects,
497// whose Pos will point back to their declaration position rather than
498// their usage position.
499func HasUniquePos(n Node) bool {
500	switch n.Op() {
501	case ONAME:
502		return false
503	case OLITERAL, ONIL, OTYPE:
504		if n.Sym() != nil {
505			return false
506		}
507	}
508
509	if !n.Pos().IsKnown() {
510		if base.Flag.K != 0 {
511			base.Warn("setlineno: unknown position (line 0)")
512		}
513		return false
514	}
515
516	return true
517}
518
519func SetPos(n Node) src.XPos {
520	lno := base.Pos
521	if n != nil && HasUniquePos(n) {
522		base.Pos = n.Pos()
523	}
524	return lno
525}
526
527// The result of InitExpr MUST be assigned back to n, e.g.
528//
529//	n.X = InitExpr(init, n.X)
530func InitExpr(init []Node, expr Node) Node {
531	if len(init) == 0 {
532		return expr
533	}
534
535	n, ok := expr.(InitNode)
536	if !ok || MayBeShared(n) {
537		// Introduce OCONVNOP to hold init list.
538		n = NewConvExpr(base.Pos, OCONVNOP, nil, expr)
539		n.SetType(expr.Type())
540		n.SetTypecheck(1)
541	}
542
543	n.PtrInit().Prepend(init...)
544	return n
545}
546
547// what's the outer value that a write to n affects?
548// outer value means containing struct or array.
549func OuterValue(n Node) Node {
550	for {
551		switch nn := n; nn.Op() {
552		case OXDOT:
553			base.FatalfAt(n.Pos(), "OXDOT in OuterValue: %v", n)
554		case ODOT:
555			nn := nn.(*SelectorExpr)
556			n = nn.X
557			continue
558		case OPAREN:
559			nn := nn.(*ParenExpr)
560			n = nn.X
561			continue
562		case OCONVNOP:
563			nn := nn.(*ConvExpr)
564			n = nn.X
565			continue
566		case OINDEX:
567			nn := nn.(*IndexExpr)
568			if nn.X.Type() == nil {
569				base.Fatalf("OuterValue needs type for %v", nn.X)
570			}
571			if nn.X.Type().IsArray() {
572				n = nn.X
573				continue
574			}
575		}
576
577		return n
578	}
579}
580
581const (
582	EscUnknown = iota
583	EscNone    // Does not escape to heap, result, or parameters.
584	EscHeap    // Reachable from the heap
585	EscNever   // By construction will not escape.
586)
587