github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/ir/expr.go (about)

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