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  	fn := NewNameAt(n.Selection.Pos, MethodSym(n.X.Type(), n.Sel), n.Type())
   585  	fn.Class = PFUNC
   586  	if n.Selection.Nname != nil {
   587  		// TODO(austin): Nname is nil for interface method
   588  		// expressions (I.M), so we can't attach a Func to
   589  		// those here.
   590  		fn.Func = n.Selection.Nname.(*Name).Func
   591  	}
   592  	return fn
   593  }
   594  
   595  // A SliceExpr is a slice expression X[Low:High] or X[Low:High:Max].
   596  type SliceExpr struct {
   597  	miniExpr
   598  	X    Node
   599  	Low  Node
   600  	High Node
   601  	Max  Node
   602  }
   603  
   604  func NewSliceExpr(pos src.XPos, op Op, x, low, high, max Node) *SliceExpr {
   605  	n := &SliceExpr{X: x, Low: low, High: high, Max: max}
   606  	n.pos = pos
   607  	n.op = op
   608  	return n
   609  }
   610  
   611  func (n *SliceExpr) SetOp(op Op) {
   612  	switch op {
   613  	default:
   614  		panic(n.no("SetOp " + op.String()))
   615  	case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
   616  		n.op = op
   617  	}
   618  }
   619  
   620  // IsSlice3 reports whether o is a slice3 op (OSLICE3, OSLICE3ARR).
   621  // o must be a slicing op.
   622  func (o Op) IsSlice3() bool {
   623  	switch o {
   624  	case OSLICE, OSLICEARR, OSLICESTR:
   625  		return false
   626  	case OSLICE3, OSLICE3ARR:
   627  		return true
   628  	}
   629  	base.Fatalf("IsSlice3 op %v", o)
   630  	return false
   631  }
   632  
   633  // A SliceHeaderExpr constructs a slice header from its parts.
   634  type SliceHeaderExpr struct {
   635  	miniExpr
   636  	Ptr Node
   637  	Len Node
   638  	Cap Node
   639  }
   640  
   641  func NewSliceHeaderExpr(pos src.XPos, typ *types.Type, ptr, len, cap Node) *SliceHeaderExpr {
   642  	n := &SliceHeaderExpr{Ptr: ptr, Len: len, Cap: cap}
   643  	n.pos = pos
   644  	n.op = OSLICEHEADER
   645  	n.typ = typ
   646  	return n
   647  }
   648  
   649  // A StringHeaderExpr expression constructs a string header from its parts.
   650  type StringHeaderExpr struct {
   651  	miniExpr
   652  	Ptr Node
   653  	Len Node
   654  }
   655  
   656  func NewStringHeaderExpr(pos src.XPos, ptr, len Node) *StringHeaderExpr {
   657  	n := &StringHeaderExpr{Ptr: ptr, Len: len}
   658  	n.pos = pos
   659  	n.op = OSTRINGHEADER
   660  	n.typ = types.Types[types.TSTRING]
   661  	return n
   662  }
   663  
   664  // A StarExpr is a dereference expression *X.
   665  // It may end up being a value or a type.
   666  type StarExpr struct {
   667  	miniExpr
   668  	X Node
   669  }
   670  
   671  func NewStarExpr(pos src.XPos, x Node) *StarExpr {
   672  	n := &StarExpr{X: x}
   673  	n.op = ODEREF
   674  	n.pos = pos
   675  	return n
   676  }
   677  
   678  func (n *StarExpr) Implicit() bool     { return n.flags&miniExprImplicit != 0 }
   679  func (n *StarExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
   680  
   681  // A TypeAssertExpr is a selector expression X.(Type).
   682  // Before type-checking, the type is Ntype.
   683  type TypeAssertExpr struct {
   684  	miniExpr
   685  	X Node
   686  
   687  	// Runtime type information provided by walkDotType for
   688  	// assertions from non-empty interface to concrete type.
   689  	ITab Node `mknode:"-"` // *runtime.itab for Type implementing X's type
   690  
   691  	// An internal/abi.TypeAssert descriptor to pass to the runtime.
   692  	Descriptor *obj.LSym
   693  
   694  	// When set to true, if this assert would panic, then use a nil pointer panic
   695  	// instead of an interface conversion panic.
   696  	// It must not be set for type assertions using the commaok form.
   697  	UseNilPanic bool
   698  }
   699  
   700  func NewTypeAssertExpr(pos src.XPos, x Node, typ *types.Type) *TypeAssertExpr {
   701  	n := &TypeAssertExpr{X: x}
   702  	n.pos = pos
   703  	n.op = ODOTTYPE
   704  	if typ != nil {
   705  		n.SetType(typ)
   706  	}
   707  	return n
   708  }
   709  
   710  func (n *TypeAssertExpr) SetOp(op Op) {
   711  	switch op {
   712  	default:
   713  		panic(n.no("SetOp " + op.String()))
   714  	case ODOTTYPE, ODOTTYPE2:
   715  		n.op = op
   716  	}
   717  }
   718  
   719  // A DynamicTypeAssertExpr asserts that X is of dynamic type RType.
   720  type DynamicTypeAssertExpr struct {
   721  	miniExpr
   722  	X Node
   723  
   724  	// SrcRType is an expression that yields a *runtime._type value
   725  	// representing X's type. It's used in failed assertion panic
   726  	// messages.
   727  	SrcRType Node
   728  
   729  	// RType is an expression that yields a *runtime._type value
   730  	// representing the asserted type.
   731  	//
   732  	// BUG(mdempsky): If ITab is non-nil, RType may be nil.
   733  	RType Node
   734  
   735  	// ITab is an expression that yields a *runtime.itab value
   736  	// representing the asserted type within the assertee expression's
   737  	// original interface type.
   738  	//
   739  	// ITab is only used for assertions from non-empty interface type to
   740  	// a concrete (i.e., non-interface) type. For all other assertions,
   741  	// ITab is nil.
   742  	ITab Node
   743  }
   744  
   745  func NewDynamicTypeAssertExpr(pos src.XPos, op Op, x, rtype Node) *DynamicTypeAssertExpr {
   746  	n := &DynamicTypeAssertExpr{X: x, RType: rtype}
   747  	n.pos = pos
   748  	n.op = op
   749  	return n
   750  }
   751  
   752  func (n *DynamicTypeAssertExpr) SetOp(op Op) {
   753  	switch op {
   754  	default:
   755  		panic(n.no("SetOp " + op.String()))
   756  	case ODYNAMICDOTTYPE, ODYNAMICDOTTYPE2:
   757  		n.op = op
   758  	}
   759  }
   760  
   761  // A UnaryExpr is a unary expression Op X,
   762  // or Op(X) for a builtin function that does not end up being a call.
   763  type UnaryExpr struct {
   764  	miniExpr
   765  	X Node
   766  }
   767  
   768  func NewUnaryExpr(pos src.XPos, op Op, x Node) *UnaryExpr {
   769  	n := &UnaryExpr{X: x}
   770  	n.pos = pos
   771  	n.SetOp(op)
   772  	return n
   773  }
   774  
   775  func (n *UnaryExpr) SetOp(op Op) {
   776  	switch op {
   777  	default:
   778  		panic(n.no("SetOp " + op.String()))
   779  	case OBITNOT, ONEG, ONOT, OPLUS, ORECV,
   780  		OCAP, OCLEAR, OCLOSE, OIMAG, OLEN, ONEW, OPANIC, OREAL,
   781  		OCHECKNIL, OCFUNC, OIDATA, OITAB, OSPTR,
   782  		OUNSAFESTRINGDATA, OUNSAFESLICEDATA:
   783  		n.op = op
   784  	}
   785  }
   786  
   787  func IsZero(n Node) bool {
   788  	switch n.Op() {
   789  	case ONIL:
   790  		return true
   791  
   792  	case OLITERAL:
   793  		switch u := n.Val(); u.Kind() {
   794  		case constant.String:
   795  			return constant.StringVal(u) == ""
   796  		case constant.Bool:
   797  			return !constant.BoolVal(u)
   798  		default:
   799  			return constant.Sign(u) == 0
   800  		}
   801  
   802  	case OARRAYLIT:
   803  		n := n.(*CompLitExpr)
   804  		for _, n1 := range n.List {
   805  			if n1.Op() == OKEY {
   806  				n1 = n1.(*KeyExpr).Value
   807  			}
   808  			if !IsZero(n1) {
   809  				return false
   810  			}
   811  		}
   812  		return true
   813  
   814  	case OSTRUCTLIT:
   815  		n := n.(*CompLitExpr)
   816  		for _, n1 := range n.List {
   817  			n1 := n1.(*StructKeyExpr)
   818  			if !IsZero(n1.Value) {
   819  				return false
   820  			}
   821  		}
   822  		return true
   823  	}
   824  
   825  	return false
   826  }
   827  
   828  // lvalue etc
   829  func IsAddressable(n Node) bool {
   830  	switch n.Op() {
   831  	case OINDEX:
   832  		n := n.(*IndexExpr)
   833  		if n.X.Type() != nil && n.X.Type().IsArray() {
   834  			return IsAddressable(n.X)
   835  		}
   836  		if n.X.Type() != nil && n.X.Type().IsString() {
   837  			return false
   838  		}
   839  		fallthrough
   840  	case ODEREF, ODOTPTR:
   841  		return true
   842  
   843  	case ODOT:
   844  		n := n.(*SelectorExpr)
   845  		return IsAddressable(n.X)
   846  
   847  	case ONAME:
   848  		n := n.(*Name)
   849  		if n.Class == PFUNC {
   850  			return false
   851  		}
   852  		return true
   853  
   854  	case OLINKSYMOFFSET:
   855  		return true
   856  	}
   857  
   858  	return false
   859  }
   860  
   861  // StaticValue analyzes n to find the earliest expression that always
   862  // evaluates to the same value as n, which might be from an enclosing
   863  // function.
   864  //
   865  // For example, given:
   866  //
   867  //	var x int = g()
   868  //	func() {
   869  //		y := x
   870  //		*p = int(y)
   871  //	}
   872  //
   873  // calling StaticValue on the "int(y)" expression returns the outer
   874  // "g()" expression.
   875  //
   876  // NOTE: StaticValue can return a result with a different type than
   877  // n's type because it can traverse through OCONVNOP operations.
   878  // TODO: consider reapplying OCONVNOP operations to the result. See https://go.dev/cl/676517.
   879  func StaticValue(n Node) Node {
   880  	for {
   881  		switch n1 := n.(type) {
   882  		case *ConvExpr:
   883  			if n1.Op() == OCONVNOP {
   884  				n = n1.X
   885  				continue
   886  			}
   887  		case *InlinedCallExpr:
   888  			if n1.Op() == OINLCALL {
   889  				n = n1.SingleResult()
   890  				continue
   891  			}
   892  		case *ParenExpr:
   893  			n = n1.X
   894  			continue
   895  		}
   896  
   897  		n1 := staticValue1(n)
   898  		if n1 == nil {
   899  			return n
   900  		}
   901  		n = n1
   902  	}
   903  }
   904  
   905  func staticValue1(nn Node) Node {
   906  	if nn.Op() != ONAME {
   907  		return nil
   908  	}
   909  	n := nn.(*Name).Canonical()
   910  	if n.Class != PAUTO {
   911  		return nil
   912  	}
   913  
   914  	defn := n.Defn
   915  	if defn == nil {
   916  		return nil
   917  	}
   918  
   919  	var rhs Node
   920  FindRHS:
   921  	switch defn.Op() {
   922  	case OAS:
   923  		defn := defn.(*AssignStmt)
   924  		rhs = defn.Y
   925  	case OAS2:
   926  		defn := defn.(*AssignListStmt)
   927  		for i, lhs := range defn.Lhs {
   928  			if lhs == n {
   929  				rhs = defn.Rhs[i]
   930  				break FindRHS
   931  			}
   932  		}
   933  		base.FatalfAt(defn.Pos(), "%v missing from LHS of %v", n, defn)
   934  	default:
   935  		return nil
   936  	}
   937  	if rhs == nil {
   938  		base.FatalfAt(defn.Pos(), "RHS is nil: %v", defn)
   939  	}
   940  
   941  	if Reassigned(n) {
   942  		return nil
   943  	}
   944  
   945  	return rhs
   946  }
   947  
   948  // Reassigned takes an ONAME node, walks the function in which it is
   949  // defined, and returns a boolean indicating whether the name has any
   950  // assignments other than its declaration.
   951  // NB: global variables are always considered to be re-assigned.
   952  // TODO: handle initial declaration not including an assignment and
   953  // followed by a single assignment?
   954  // NOTE: any changes made here should also be made in the corresponding
   955  // code in the ReassignOracle.Init method.
   956  func Reassigned(name *Name) bool {
   957  	if name.Op() != ONAME {
   958  		base.Fatalf("reassigned %v", name)
   959  	}
   960  	// no way to reliably check for no-reassignment of globals, assume it can be
   961  	if name.Curfn == nil {
   962  		return true
   963  	}
   964  
   965  	if name.Addrtaken() {
   966  		return true // conservatively assume it's reassigned indirectly
   967  	}
   968  
   969  	// TODO(mdempsky): This is inefficient and becoming increasingly
   970  	// unwieldy. Figure out a way to generalize escape analysis's
   971  	// reassignment detection for use by inlining and devirtualization.
   972  
   973  	// isName reports whether n is a reference to name.
   974  	isName := func(x Node) bool {
   975  		if x == nil {
   976  			return false
   977  		}
   978  		n, ok := OuterValue(x).(*Name)
   979  		return ok && n.Canonical() == name
   980  	}
   981  
   982  	var do func(n Node) bool
   983  	do = func(n Node) bool {
   984  		switch n.Op() {
   985  		case OAS:
   986  			n := n.(*AssignStmt)
   987  			if isName(n.X) && n != name.Defn {
   988  				return true
   989  			}
   990  		case OAS2, OAS2FUNC, OAS2MAPR, OAS2DOTTYPE, OAS2RECV, OSELRECV2:
   991  			n := n.(*AssignListStmt)
   992  			for _, p := range n.Lhs {
   993  				if isName(p) && n != name.Defn {
   994  					return true
   995  				}
   996  			}
   997  		case OASOP:
   998  			n := n.(*AssignOpStmt)
   999  			if isName(n.X) {
  1000  				return true
  1001  			}
  1002  		case OADDR:
  1003  			n := n.(*AddrExpr)
  1004  			if isName(n.X) {
  1005  				base.FatalfAt(n.Pos(), "%v not marked addrtaken", name)
  1006  			}
  1007  		case ORANGE:
  1008  			n := n.(*RangeStmt)
  1009  			if isName(n.Key) || isName(n.Value) {
  1010  				return true
  1011  			}
  1012  		case OCLOSURE:
  1013  			n := n.(*ClosureExpr)
  1014  			if Any(n.Func, do) {
  1015  				return true
  1016  			}
  1017  		}
  1018  		return false
  1019  	}
  1020  	return Any(name.Curfn, do)
  1021  }
  1022  
  1023  // FuncSingleAssignment returns the sole OAS *AssignStmt that assigns a
  1024  // non-zero value to name, if name is a func-typed local variable (PAUTO)
  1025  // with exactly one such assignment. Zero-value assignments (nil, bare
  1026  // declarations) are ignored since nil panics on call. Returns nil if the
  1027  // variable is not PAUTO, not func-typed, address-taken, has multiple
  1028  // non-zero assignments, or has any complex assignments (OAS2, ORANGE).
  1029  // Assignments inside nested closures are accepted because this is only
  1030  // used for escape analysis callee resolution: the only alternative value
  1031  // is nil, which panics on call.
  1032  //
  1033  // TODO: fold this into [ReassignOracle] so it can share the single
  1034  // walk with StaticValue and Reassigned.
  1035  func FuncSingleAssignment(name *Name) *AssignStmt {
  1036  	if name.Class != PAUTO {
  1037  		return nil
  1038  	}
  1039  	base.AssertfAt(name.Curfn != nil, name.Pos(), "PAUTO %v has nil Curfn", name)
  1040  	if name.Addrtaken() {
  1041  		return nil
  1042  	}
  1043  	if name.Type().Kind() != types.TFUNC {
  1044  		return nil
  1045  	}
  1046  	// Reject variables with non-zero defining assignments we can't
  1047  	// analyze (e.g., type switch case variables whose Defn is a
  1048  	// TypeSwitchGuard, not an AssignStmt).
  1049  	if name.Defn != nil {
  1050  		as, ok := name.Defn.(*AssignStmt)
  1051  		if !ok || !isNilAssign(as) {
  1052  			return nil
  1053  		}
  1054  	}
  1055  
  1056  	isName := func(x Node) bool {
  1057  		if x == nil {
  1058  			return false
  1059  		}
  1060  		n, ok := OuterValue(x).(*Name)
  1061  		return ok && n.Canonical() == name
  1062  	}
  1063  
  1064  	var found *AssignStmt
  1065  
  1066  	var do func(n Node) bool
  1067  	do = func(n Node) bool {
  1068  		switch n.Op() {
  1069  		case OAS:
  1070  			as := n.(*AssignStmt)
  1071  			if isName(as.X) {
  1072  				if isNilAssign(as) {
  1073  					break
  1074  				}
  1075  				if found != nil {
  1076  					found = nil
  1077  					return true
  1078  				}
  1079  				found = as
  1080  			}
  1081  		case OAS2, OAS2FUNC, OAS2MAPR, OAS2DOTTYPE, OAS2RECV, OSELRECV2:
  1082  			as := n.(*AssignListStmt)
  1083  			for _, p := range as.Lhs {
  1084  				if isName(p) {
  1085  					found = nil
  1086  					return true
  1087  				}
  1088  			}
  1089  		case ORANGE:
  1090  			rs := n.(*RangeStmt)
  1091  			if isName(rs.Key) || isName(rs.Value) {
  1092  				found = nil
  1093  				return true
  1094  			}
  1095  		case OCLOSURE:
  1096  			n := n.(*ClosureExpr)
  1097  			if Any(n.Func, do) {
  1098  				return true
  1099  			}
  1100  		}
  1101  		return false
  1102  	}
  1103  
  1104  	if Any(name.Curfn, do) {
  1105  		return nil
  1106  	}
  1107  	return found
  1108  }
  1109  
  1110  // isNilAssign reports whether as has a nil or absent RHS.
  1111  func isNilAssign(as *AssignStmt) bool {
  1112  	if as.Y == nil {
  1113  		return true
  1114  	}
  1115  	y := as.Y
  1116  	for y.Op() == OCONVNOP {
  1117  		y = y.(*ConvExpr).X
  1118  	}
  1119  	return IsNil(y)
  1120  }
  1121  
  1122  // StaticCalleeName returns the ONAME/PFUNC for n, if known.
  1123  func StaticCalleeName(n Node) *Name {
  1124  	switch n.Op() {
  1125  	case OMETHEXPR:
  1126  		n := n.(*SelectorExpr)
  1127  		return MethodExprName(n)
  1128  	case ONAME:
  1129  		n := n.(*Name)
  1130  		if n.Class == PFUNC {
  1131  			return n
  1132  		}
  1133  	case OCLOSURE:
  1134  		return n.(*ClosureExpr).Func.Nname
  1135  	}
  1136  	return nil
  1137  }
  1138  
  1139  // IsIntrinsicCall reports whether the compiler back end will treat the call as an intrinsic operation.
  1140  var IsIntrinsicCall = func(*CallExpr) bool { return false }
  1141  
  1142  // IsIntrinsicSym reports whether the compiler back end will treat a call to this symbol as an intrinsic operation.
  1143  var IsIntrinsicSym = func(*types.Sym) bool { return false }
  1144  
  1145  // SameSafeExpr checks whether it is safe to reuse one of l and r
  1146  // instead of computing both. SameSafeExpr assumes that l and r are
  1147  // used in the same statement or expression. In order for it to be
  1148  // safe to reuse l or r, they must:
  1149  //   - be the same expression
  1150  //   - not have side-effects (no function calls, no channel ops);
  1151  //     however, panics are ok
  1152  //   - not cause inappropriate aliasing; e.g. two string to []byte
  1153  //     conversions, must result in two distinct slices
  1154  //
  1155  // The handling of OINDEXMAP is subtle. OINDEXMAP can occur both
  1156  // as an lvalue (map assignment) and an rvalue (map access). This is
  1157  // currently OK, since the only place SameSafeExpr gets used on an
  1158  // lvalue expression is for OSLICE and OAPPEND optimizations, and it
  1159  // is correct in those settings.
  1160  func SameSafeExpr(l Node, r Node) bool {
  1161  	for l.Op() == OCONVNOP {
  1162  		l = l.(*ConvExpr).X
  1163  	}
  1164  	for r.Op() == OCONVNOP {
  1165  		r = r.(*ConvExpr).X
  1166  	}
  1167  	if l.Op() != r.Op() || !types.Identical(l.Type(), r.Type()) {
  1168  		return false
  1169  	}
  1170  
  1171  	switch l.Op() {
  1172  	case ONAME:
  1173  		return l == r
  1174  
  1175  	case ODOT, ODOTPTR:
  1176  		l := l.(*SelectorExpr)
  1177  		r := r.(*SelectorExpr)
  1178  		return l.Sel != nil && r.Sel != nil && l.Sel == r.Sel && SameSafeExpr(l.X, r.X)
  1179  
  1180  	case ODEREF:
  1181  		l := l.(*StarExpr)
  1182  		r := r.(*StarExpr)
  1183  		return SameSafeExpr(l.X, r.X)
  1184  
  1185  	case ONOT, OBITNOT, OPLUS, ONEG:
  1186  		l := l.(*UnaryExpr)
  1187  		r := r.(*UnaryExpr)
  1188  		return SameSafeExpr(l.X, r.X)
  1189  
  1190  	case OCONV:
  1191  		l := l.(*ConvExpr)
  1192  		r := r.(*ConvExpr)
  1193  		// Some conversions can't be reused, such as []byte(str).
  1194  		// Allow only numeric-ish types. This is a bit conservative.
  1195  		return types.IsSimple[l.Type().Kind()] && SameSafeExpr(l.X, r.X)
  1196  
  1197  	case OINDEX, OINDEXMAP:
  1198  		l := l.(*IndexExpr)
  1199  		r := r.(*IndexExpr)
  1200  		return SameSafeExpr(l.X, r.X) && SameSafeExpr(l.Index, r.Index)
  1201  
  1202  	case OADD, OSUB, OOR, OXOR, OMUL, OLSH, ORSH, OAND, OANDNOT, ODIV, OMOD:
  1203  		l := l.(*BinaryExpr)
  1204  		r := r.(*BinaryExpr)
  1205  		return SameSafeExpr(l.X, r.X) && SameSafeExpr(l.Y, r.Y)
  1206  
  1207  	case OLITERAL:
  1208  		return constant.Compare(l.Val(), token.EQL, r.Val())
  1209  
  1210  	case ONIL:
  1211  		return true
  1212  	}
  1213  
  1214  	return false
  1215  }
  1216  
  1217  // ShouldCheckPtr reports whether pointer checking should be enabled for
  1218  // function fn at a given level. See debugHelpFooter for defined
  1219  // levels.
  1220  func ShouldCheckPtr(fn *Func, level int) bool {
  1221  	return base.Debug.Checkptr >= level && fn.Pragma&NoCheckPtr == 0
  1222  }
  1223  
  1224  // ShouldAsanCheckPtr reports whether pointer checking should be enabled for
  1225  // function fn when -asan is enabled.
  1226  func ShouldAsanCheckPtr(fn *Func) bool {
  1227  	return base.Flag.ASan && fn.Pragma&NoCheckPtr == 0
  1228  }
  1229  
  1230  // IsReflectHeaderDataField reports whether l is an expression p.Data
  1231  // where p has type reflect.SliceHeader or reflect.StringHeader.
  1232  func IsReflectHeaderDataField(l Node) bool {
  1233  	if l.Type() != types.Types[types.TUINTPTR] {
  1234  		return false
  1235  	}
  1236  
  1237  	var tsym *types.Sym
  1238  	switch l.Op() {
  1239  	case ODOT:
  1240  		l := l.(*SelectorExpr)
  1241  		tsym = l.X.Type().Sym()
  1242  	case ODOTPTR:
  1243  		l := l.(*SelectorExpr)
  1244  		tsym = l.X.Type().Elem().Sym()
  1245  	default:
  1246  		return false
  1247  	}
  1248  
  1249  	if tsym == nil || l.Sym().Name != "Data" || tsym.Pkg.Path != "reflect" {
  1250  		return false
  1251  	}
  1252  	return tsym.Name == "SliceHeader" || tsym.Name == "StringHeader"
  1253  }
  1254  
  1255  func ParamNames(ft *types.Type) []Node {
  1256  	args := make([]Node, ft.NumParams())
  1257  	for i, f := range ft.Params() {
  1258  		args[i] = f.Nname.(*Name)
  1259  	}
  1260  	return args
  1261  }
  1262  
  1263  func RecvParamNames(ft *types.Type) []Node {
  1264  	args := make([]Node, ft.NumRecvs()+ft.NumParams())
  1265  	for i, f := range ft.RecvParams() {
  1266  		args[i] = f.Nname.(*Name)
  1267  	}
  1268  	return args
  1269  }
  1270  
  1271  // MethodSym returns the method symbol representing a method name
  1272  // associated with a specific receiver type.
  1273  //
  1274  // Method symbols can be used to distinguish the same method appearing
  1275  // in different method sets. For example, T.M and (*T).M have distinct
  1276  // method symbols.
  1277  //
  1278  // The returned symbol will be marked as a function.
  1279  func MethodSym(recv *types.Type, msym *types.Sym) *types.Sym {
  1280  	sym := MethodSymSuffix(recv, msym, "")
  1281  	sym.SetFunc(true)
  1282  	return sym
  1283  }
  1284  
  1285  // MethodSymSuffix is like MethodSym, but allows attaching a
  1286  // distinguisher suffix. To avoid collisions, the suffix must not
  1287  // start with a letter, number, or period.
  1288  func MethodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sym {
  1289  	if msym.IsBlank() {
  1290  		base.Fatalf("blank method name")
  1291  	}
  1292  
  1293  	rsym := recv.Sym()
  1294  	if recv.IsPtr() {
  1295  		if rsym != nil {
  1296  			base.Fatalf("declared pointer receiver type: %v", recv)
  1297  		}
  1298  		rsym = recv.Elem().Sym()
  1299  	}
  1300  
  1301  	// Find the package the receiver type appeared in. For
  1302  	// anonymous receiver types (i.e., anonymous structs with
  1303  	// embedded fields), use the "go" pseudo-package instead.
  1304  	rpkg := Pkgs.Go
  1305  	if rsym != nil {
  1306  		rpkg = rsym.Pkg
  1307  	}
  1308  
  1309  	var b bytes.Buffer
  1310  	if recv.IsPtr() {
  1311  		// The parentheses aren't really necessary, but
  1312  		// they're pretty traditional at this point.
  1313  		fmt.Fprintf(&b, "(%-S)", recv)
  1314  	} else {
  1315  		fmt.Fprintf(&b, "%-S", recv)
  1316  	}
  1317  
  1318  	// A particular receiver type may have multiple non-exported
  1319  	// methods with the same name. To disambiguate them, include a
  1320  	// package qualifier for names that came from a different
  1321  	// package than the receiver type.
  1322  	if !types.IsExported(msym.Name) && msym.Pkg != rpkg {
  1323  		b.WriteString(".")
  1324  		b.WriteString(msym.Pkg.Prefix)
  1325  	}
  1326  
  1327  	b.WriteString(".")
  1328  	b.WriteString(msym.Name)
  1329  	b.WriteString(suffix)
  1330  	return rpkg.LookupBytes(b.Bytes())
  1331  }
  1332  
  1333  // LookupMethodSelector returns the types.Sym of the selector for a method
  1334  // named in local symbol name, as well as the types.Sym of the receiver.
  1335  //
  1336  // TODO(prattmic): this does not attempt to handle method suffixes (wrappers).
  1337  func LookupMethodSelector(pkg *types.Pkg, name string) (typ, meth *types.Sym, err error) {
  1338  	typeName, methName := splitType(name)
  1339  	if typeName == "" {
  1340  		return nil, nil, fmt.Errorf("%s doesn't contain type split", name)
  1341  	}
  1342  
  1343  	if len(typeName) > 3 && typeName[:2] == "(*" && typeName[len(typeName)-1] == ')' {
  1344  		// Symbol name is for a pointer receiver method. We just want
  1345  		// the base type name.
  1346  		typeName = typeName[2 : len(typeName)-1]
  1347  	}
  1348  
  1349  	typ = pkg.Lookup(typeName)
  1350  	meth = pkg.Selector(methName)
  1351  	return typ, meth, nil
  1352  }
  1353  
  1354  // splitType splits a local symbol name into type and method (fn). If this a
  1355  // free function, typ == "".
  1356  //
  1357  // N.B. closures and methods can be ambiguous (e.g., bar.func1). These cases
  1358  // are returned as methods.
  1359  func splitType(name string) (typ, fn string) {
  1360  	// Types are split on the first dot, ignoring everything inside
  1361  	// brackets (instantiation of type parameter, usually including
  1362  	// "go.shape").
  1363  	bracket := 0
  1364  	for i, r := range name {
  1365  		if r == '.' && bracket == 0 {
  1366  			return name[:i], name[i+1:]
  1367  		}
  1368  		if r == '[' {
  1369  			bracket++
  1370  		}
  1371  		if r == ']' {
  1372  			bracket--
  1373  		}
  1374  	}
  1375  	return "", name
  1376  }
  1377  
  1378  // MethodExprName returns the ONAME representing the method
  1379  // referenced by expression n, which must be a method selector,
  1380  // method expression, or method value.
  1381  func MethodExprName(n Node) *Name {
  1382  	name, _ := MethodExprFunc(n).Nname.(*Name)
  1383  	return name
  1384  }
  1385  
  1386  // MethodExprFunc is like MethodExprName, but returns the types.Field instead.
  1387  func MethodExprFunc(n Node) *types.Field {
  1388  	switch n.Op() {
  1389  	case ODOTMETH, OMETHEXPR, OMETHVALUE:
  1390  		return n.(*SelectorExpr).Selection
  1391  	}
  1392  	base.Fatalf("unexpected node: %v (%v)", n, n.Op())
  1393  	panic("unreachable")
  1394  }
  1395  
  1396  // A MoveToHeapExpr takes a slice as input and moves it to the
  1397  // heap (by copying the backing store if it is not already
  1398  // on the heap).
  1399  type MoveToHeapExpr struct {
  1400  	miniExpr
  1401  	Slice Node
  1402  	// An expression that evaluates to a *runtime._type
  1403  	// that represents the slice element type.
  1404  	RType Node
  1405  	// If PreserveCapacity is true, the capacity of
  1406  	// the resulting slice, and all of the elements in
  1407  	// [len:cap], must be preserved.
  1408  	// If PreserveCapacity is false, the resulting
  1409  	// slice may have any capacity >= len, with any
  1410  	// elements in the resulting [len:cap] range zeroed.
  1411  	PreserveCapacity bool
  1412  }
  1413  
  1414  func NewMoveToHeapExpr(pos src.XPos, slice Node) *MoveToHeapExpr {
  1415  	n := &MoveToHeapExpr{Slice: slice}
  1416  	n.pos = pos
  1417  	n.op = OMOVE2HEAP
  1418  	return n
  1419  }
  1420  

View as plain text