Source file src/cmd/compile/internal/ir/expr.go

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

View as plain text