github.com/bir3/gocompiler@v0.3.205/src/cmd/compile/internal/ir/expr.go (about)

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