Source file src/cmd/compile/internal/ir/name.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  	"cmd/compile/internal/base"
     9  	"cmd/compile/internal/types"
    10  	"cmd/internal/obj"
    11  	"cmd/internal/objabi"
    12  	"cmd/internal/src"
    13  	"fmt"
    14  
    15  	"go/constant"
    16  )
    17  
    18  // An Ident is an identifier, possibly qualified.
    19  type Ident struct {
    20  	miniExpr
    21  	sym *types.Sym
    22  }
    23  
    24  func NewIdent(pos src.XPos, sym *types.Sym) *Ident {
    25  	n := new(Ident)
    26  	n.op = ONONAME
    27  	n.pos = pos
    28  	n.sym = sym
    29  	return n
    30  }
    31  
    32  func (n *Ident) Sym() *types.Sym { return n.sym }
    33  
    34  func (*Ident) CanBeNtype() {}
    35  
    36  // Name holds Node fields used only by named nodes (ONAME, OTYPE, some OLITERAL).
    37  type Name struct {
    38  	miniExpr
    39  	BuiltinOp Op         // uint8
    40  	Class     Class      // uint8
    41  	pragma    PragmaFlag // int16
    42  	flags     bitset16
    43  	DictIndex uint16 // index of the dictionary entry describing the type of this variable declaration plus 1
    44  	sym       *types.Sym
    45  	Func      *Func // TODO(austin): nil for I.M, eqFor, hashfor, and hashmem
    46  	Offset_   int64
    47  	val       constant.Value
    48  	Opt       interface{} // for use by escape analysis
    49  	Embed     *[]Embed    // list of embedded files, for ONAME var
    50  
    51  	PkgName *PkgName // real package for import . names
    52  	// For a local variable (not param) or extern, the initializing assignment (OAS or OAS2).
    53  	// For a closure var, the ONAME node of the outer captured variable.
    54  	// For the case-local variables of a type switch, the type switch guard (OTYPESW).
    55  	// For a range variable, the range statement (ORANGE)
    56  	// For a recv variable in a case of a select statement, the receive assignment (OSELRECV2)
    57  	// For the name of a function, points to corresponding Func node.
    58  	Defn Node
    59  
    60  	// The function, method, or closure in which local variable or param is declared.
    61  	Curfn *Func
    62  
    63  	Ntype    Ntype
    64  	Heapaddr *Name // temp holding heap address of param
    65  
    66  	// ONAME closure linkage
    67  	// Consider:
    68  	//
    69  	//	func f() {
    70  	//		x := 1 // x1
    71  	//		func() {
    72  	//			use(x) // x2
    73  	//			func() {
    74  	//				use(x) // x3
    75  	//				--- parser is here ---
    76  	//			}()
    77  	//		}()
    78  	//	}
    79  	//
    80  	// There is an original declaration of x and then a chain of mentions of x
    81  	// leading into the current function. Each time x is mentioned in a new closure,
    82  	// we create a variable representing x for use in that specific closure,
    83  	// since the way you get to x is different in each closure.
    84  	//
    85  	// Let's number the specific variables as shown in the code:
    86  	// x1 is the original x, x2 is when mentioned in the closure,
    87  	// and x3 is when mentioned in the closure in the closure.
    88  	//
    89  	// We keep these linked (assume N > 1):
    90  	//
    91  	//   - x1.Defn = original declaration statement for x (like most variables)
    92  	//   - x1.Innermost = current innermost closure x (in this case x3), or nil for none
    93  	//   - x1.IsClosureVar() = false
    94  	//
    95  	//   - xN.Defn = x1, N > 1
    96  	//   - xN.IsClosureVar() = true, N > 1
    97  	//   - x2.Outer = nil
    98  	//   - xN.Outer = x(N-1), N > 2
    99  	//
   100  	//
   101  	// When we look up x in the symbol table, we always get x1.
   102  	// Then we can use x1.Innermost (if not nil) to get the x
   103  	// for the innermost known closure function,
   104  	// but the first reference in a closure will find either no x1.Innermost
   105  	// or an x1.Innermost with .Funcdepth < Funcdepth.
   106  	// In that case, a new xN must be created, linked in with:
   107  	//
   108  	//     xN.Defn = x1
   109  	//     xN.Outer = x1.Innermost
   110  	//     x1.Innermost = xN
   111  	//
   112  	// When we finish the function, we'll process its closure variables
   113  	// and find xN and pop it off the list using:
   114  	//
   115  	//     x1 := xN.Defn
   116  	//     x1.Innermost = xN.Outer
   117  	//
   118  	// We leave x1.Innermost set so that we can still get to the original
   119  	// variable quickly. Not shown here, but once we're
   120  	// done parsing a function and no longer need xN.Outer for the
   121  	// lexical x reference links as described above, funcLit
   122  	// recomputes xN.Outer as the semantic x reference link tree,
   123  	// even filling in x in intermediate closures that might not
   124  	// have mentioned it along the way to inner closures that did.
   125  	// See funcLit for details.
   126  	//
   127  	// During the eventual compilation, then, for closure variables we have:
   128  	//
   129  	//     xN.Defn = original variable
   130  	//     xN.Outer = variable captured in next outward scope
   131  	//                to make closure where xN appears
   132  	//
   133  	// Because of the sharding of pieces of the node, x.Defn means x.Name.Defn
   134  	// and x.Innermost/Outer means x.Name.Param.Innermost/Outer.
   135  	Innermost *Name
   136  	Outer     *Name
   137  }
   138  
   139  func (n *Name) isExpr() {}
   140  
   141  func (n *Name) copy() Node                         { panic(n.no("copy")) }
   142  func (n *Name) doChildren(do func(Node) bool) bool { return false }
   143  func (n *Name) editChildren(edit func(Node) Node)  {}
   144  
   145  // TypeDefn returns the type definition for a named OTYPE.
   146  // That is, given "type T Defn", it returns Defn.
   147  // It is used by package types.
   148  func (n *Name) TypeDefn() *types.Type {
   149  	if n.Ntype != nil {
   150  		return n.Ntype.Type()
   151  	}
   152  	return n.Type()
   153  }
   154  
   155  // RecordFrameOffset records the frame offset for the name.
   156  // It is used by package types when laying out function arguments.
   157  func (n *Name) RecordFrameOffset(offset int64) {
   158  	n.SetFrameOffset(offset)
   159  }
   160  
   161  // NewNameAt returns a new ONAME Node associated with symbol s at position pos.
   162  // The caller is responsible for setting Curfn.
   163  func NewNameAt(pos src.XPos, sym *types.Sym) *Name {
   164  	if sym == nil {
   165  		base.Fatalf("NewNameAt nil")
   166  	}
   167  	return newNameAt(pos, ONAME, sym)
   168  }
   169  
   170  // NewIota returns a new OIOTA Node.
   171  func NewIota(pos src.XPos, sym *types.Sym) *Name {
   172  	if sym == nil {
   173  		base.Fatalf("NewIota nil")
   174  	}
   175  	return newNameAt(pos, OIOTA, sym)
   176  }
   177  
   178  // NewDeclNameAt returns a new Name associated with symbol s at position pos.
   179  // The caller is responsible for setting Curfn.
   180  func NewDeclNameAt(pos src.XPos, op Op, sym *types.Sym) *Name {
   181  	if sym == nil {
   182  		base.Fatalf("NewDeclNameAt nil")
   183  	}
   184  	switch op {
   185  	case ONAME, OTYPE, OLITERAL:
   186  		// ok
   187  	default:
   188  		base.Fatalf("NewDeclNameAt op %v", op)
   189  	}
   190  	return newNameAt(pos, op, sym)
   191  }
   192  
   193  // NewConstAt returns a new OLITERAL Node associated with symbol s at position pos.
   194  func NewConstAt(pos src.XPos, sym *types.Sym, typ *types.Type, val constant.Value) *Name {
   195  	if sym == nil {
   196  		base.Fatalf("NewConstAt nil")
   197  	}
   198  	n := newNameAt(pos, OLITERAL, sym)
   199  	n.SetType(typ)
   200  	n.SetVal(val)
   201  	return n
   202  }
   203  
   204  // newNameAt is like NewNameAt but allows sym == nil.
   205  func newNameAt(pos src.XPos, op Op, sym *types.Sym) *Name {
   206  	n := new(Name)
   207  	n.op = op
   208  	n.pos = pos
   209  	n.sym = sym
   210  	return n
   211  }
   212  
   213  func (n *Name) Name() *Name         { return n }
   214  func (n *Name) Sym() *types.Sym     { return n.sym }
   215  func (n *Name) SetSym(x *types.Sym) { n.sym = x }
   216  func (n *Name) SubOp() Op           { return n.BuiltinOp }
   217  func (n *Name) SetSubOp(x Op)       { n.BuiltinOp = x }
   218  func (n *Name) SetFunc(x *Func)     { n.Func = x }
   219  func (n *Name) Offset() int64       { panic("Name.Offset") }
   220  func (n *Name) SetOffset(x int64) {
   221  	if x != 0 {
   222  		panic("Name.SetOffset")
   223  	}
   224  }
   225  func (n *Name) FrameOffset() int64     { return n.Offset_ }
   226  func (n *Name) SetFrameOffset(x int64) { n.Offset_ = x }
   227  func (n *Name) Iota() int64            { return n.Offset_ }
   228  func (n *Name) SetIota(x int64)        { n.Offset_ = x }
   229  func (n *Name) Walkdef() uint8         { return n.bits.get2(miniWalkdefShift) }
   230  func (n *Name) SetWalkdef(x uint8) {
   231  	if x > 3 {
   232  		panic(fmt.Sprintf("cannot SetWalkdef %d", x))
   233  	}
   234  	n.bits.set2(miniWalkdefShift, x)
   235  }
   236  
   237  func (n *Name) Linksym() *obj.LSym               { return n.sym.Linksym() }
   238  func (n *Name) LinksymABI(abi obj.ABI) *obj.LSym { return n.sym.LinksymABI(abi) }
   239  
   240  func (*Name) CanBeNtype()    {}
   241  func (*Name) CanBeAnSSASym() {}
   242  func (*Name) CanBeAnSSAAux() {}
   243  
   244  // Pragma returns the PragmaFlag for p, which must be for an OTYPE.
   245  func (n *Name) Pragma() PragmaFlag { return n.pragma }
   246  
   247  // SetPragma sets the PragmaFlag for p, which must be for an OTYPE.
   248  func (n *Name) SetPragma(flag PragmaFlag) { n.pragma = flag }
   249  
   250  // Alias reports whether p, which must be for an OTYPE, is a type alias.
   251  func (n *Name) Alias() bool { return n.flags&nameAlias != 0 }
   252  
   253  // SetAlias sets whether p, which must be for an OTYPE, is a type alias.
   254  func (n *Name) SetAlias(alias bool) { n.flags.set(nameAlias, alias) }
   255  
   256  const (
   257  	nameReadonly                 = 1 << iota
   258  	nameByval                    // is the variable captured by value or by reference
   259  	nameNeedzero                 // if it contains pointers, needs to be zeroed on function entry
   260  	nameAutoTemp                 // is the variable a temporary (implies no dwarf info. reset if escapes to heap)
   261  	nameUsed                     // for variable declared and not used error
   262  	nameIsClosureVar             // PAUTOHEAP closure pseudo-variable; original (if any) at n.Defn
   263  	nameIsOutputParamHeapAddr    // pointer to a result parameter's heap copy
   264  	nameIsOutputParamInRegisters // output parameter in registers spills as an auto
   265  	nameAddrtaken                // address taken, even if not moved to heap
   266  	nameInlFormal                // PAUTO created by inliner, derived from callee formal
   267  	nameInlLocal                 // PAUTO created by inliner, derived from callee local
   268  	nameOpenDeferSlot            // if temporary var storing info for open-coded defers
   269  	nameLibfuzzerExtraCounter    // if PEXTERN should be assigned to __libfuzzer_extra_counters section
   270  	nameAlias                    // is type name an alias
   271  )
   272  
   273  func (n *Name) Readonly() bool                 { return n.flags&nameReadonly != 0 }
   274  func (n *Name) Needzero() bool                 { return n.flags&nameNeedzero != 0 }
   275  func (n *Name) AutoTemp() bool                 { return n.flags&nameAutoTemp != 0 }
   276  func (n *Name) Used() bool                     { return n.flags&nameUsed != 0 }
   277  func (n *Name) IsClosureVar() bool             { return n.flags&nameIsClosureVar != 0 }
   278  func (n *Name) IsOutputParamHeapAddr() bool    { return n.flags&nameIsOutputParamHeapAddr != 0 }
   279  func (n *Name) IsOutputParamInRegisters() bool { return n.flags&nameIsOutputParamInRegisters != 0 }
   280  func (n *Name) Addrtaken() bool                { return n.flags&nameAddrtaken != 0 }
   281  func (n *Name) InlFormal() bool                { return n.flags&nameInlFormal != 0 }
   282  func (n *Name) InlLocal() bool                 { return n.flags&nameInlLocal != 0 }
   283  func (n *Name) OpenDeferSlot() bool            { return n.flags&nameOpenDeferSlot != 0 }
   284  func (n *Name) LibfuzzerExtraCounter() bool    { return n.flags&nameLibfuzzerExtraCounter != 0 }
   285  
   286  func (n *Name) setReadonly(b bool)                 { n.flags.set(nameReadonly, b) }
   287  func (n *Name) SetNeedzero(b bool)                 { n.flags.set(nameNeedzero, b) }
   288  func (n *Name) SetAutoTemp(b bool)                 { n.flags.set(nameAutoTemp, b) }
   289  func (n *Name) SetUsed(b bool)                     { n.flags.set(nameUsed, b) }
   290  func (n *Name) SetIsClosureVar(b bool)             { n.flags.set(nameIsClosureVar, b) }
   291  func (n *Name) SetIsOutputParamHeapAddr(b bool)    { n.flags.set(nameIsOutputParamHeapAddr, b) }
   292  func (n *Name) SetIsOutputParamInRegisters(b bool) { n.flags.set(nameIsOutputParamInRegisters, b) }
   293  func (n *Name) SetAddrtaken(b bool)                { n.flags.set(nameAddrtaken, b) }
   294  func (n *Name) SetInlFormal(b bool)                { n.flags.set(nameInlFormal, b) }
   295  func (n *Name) SetInlLocal(b bool)                 { n.flags.set(nameInlLocal, b) }
   296  func (n *Name) SetOpenDeferSlot(b bool)            { n.flags.set(nameOpenDeferSlot, b) }
   297  func (n *Name) SetLibfuzzerExtraCounter(b bool)    { n.flags.set(nameLibfuzzerExtraCounter, b) }
   298  
   299  // OnStack reports whether variable n may reside on the stack.
   300  func (n *Name) OnStack() bool {
   301  	if n.Op() == ONAME {
   302  		switch n.Class {
   303  		case PPARAM, PPARAMOUT, PAUTO:
   304  			return n.Esc() != EscHeap
   305  		case PEXTERN, PAUTOHEAP:
   306  			return false
   307  		}
   308  	}
   309  	// Note: fmt.go:dumpNodeHeader calls all "func() bool"-typed
   310  	// methods, but it can only recover from panics, not Fatalf.
   311  	panic(fmt.Sprintf("%v: not a variable: %v", base.FmtPos(n.Pos()), n))
   312  }
   313  
   314  // MarkReadonly indicates that n is an ONAME with readonly contents.
   315  func (n *Name) MarkReadonly() {
   316  	if n.Op() != ONAME {
   317  		base.Fatalf("Node.MarkReadonly %v", n.Op())
   318  	}
   319  	n.setReadonly(true)
   320  	// Mark the linksym as readonly immediately
   321  	// so that the SSA backend can use this information.
   322  	// It will be overridden later during dumpglobls.
   323  	n.Linksym().Type = objabi.SRODATA
   324  }
   325  
   326  // Val returns the constant.Value for the node.
   327  func (n *Name) Val() constant.Value {
   328  	if n.val == nil {
   329  		return constant.MakeUnknown()
   330  	}
   331  	return n.val
   332  }
   333  
   334  // SetVal sets the constant.Value for the node.
   335  func (n *Name) SetVal(v constant.Value) {
   336  	if n.op != OLITERAL {
   337  		panic(n.no("SetVal"))
   338  	}
   339  	AssertValidTypeForConst(n.Type(), v)
   340  	n.val = v
   341  }
   342  
   343  // Canonical returns the logical declaration that n represents. If n
   344  // is a closure variable, then Canonical returns the original Name as
   345  // it appears in the function that immediately contains the
   346  // declaration. Otherwise, Canonical simply returns n itself.
   347  func (n *Name) Canonical() *Name {
   348  	if n.IsClosureVar() && n.Defn != nil {
   349  		n = n.Defn.(*Name)
   350  	}
   351  	return n
   352  }
   353  
   354  func (n *Name) SetByval(b bool) {
   355  	if n.Canonical() != n {
   356  		base.Fatalf("SetByval called on non-canonical variable: %v", n)
   357  	}
   358  	n.flags.set(nameByval, b)
   359  }
   360  
   361  func (n *Name) Byval() bool {
   362  	// We require byval to be set on the canonical variable, but we
   363  	// allow it to be accessed from any instance.
   364  	return n.Canonical().flags&nameByval != 0
   365  }
   366  
   367  // NewClosureVar returns a new closure variable for fn to refer to
   368  // outer variable n.
   369  func NewClosureVar(pos src.XPos, fn *Func, n *Name) *Name {
   370  	c := NewNameAt(pos, n.Sym())
   371  	c.Curfn = fn
   372  	c.Class = PAUTOHEAP
   373  	c.SetIsClosureVar(true)
   374  	c.Defn = n.Canonical()
   375  	c.Outer = n
   376  
   377  	c.SetType(n.Type())
   378  	c.SetTypecheck(n.Typecheck())
   379  
   380  	fn.ClosureVars = append(fn.ClosureVars, c)
   381  
   382  	return c
   383  }
   384  
   385  // NewHiddenParam returns a new hidden parameter for fn with the given
   386  // name and type.
   387  func NewHiddenParam(pos src.XPos, fn *Func, sym *types.Sym, typ *types.Type) *Name {
   388  	if fn.OClosure != nil {
   389  		base.FatalfAt(fn.Pos(), "cannot add hidden parameters to closures")
   390  	}
   391  
   392  	fn.SetNeedctxt(true)
   393  
   394  	// Create a fake parameter, disassociated from any real function, to
   395  	// pretend to capture.
   396  	fake := NewNameAt(pos, sym)
   397  	fake.Class = PPARAM
   398  	fake.SetType(typ)
   399  	fake.SetByval(true)
   400  
   401  	return NewClosureVar(pos, fn, fake)
   402  }
   403  
   404  // CaptureName returns a Name suitable for referring to n from within function
   405  // fn or from the package block if fn is nil. If n is a free variable declared
   406  // within a function that encloses fn, then CaptureName returns the closure
   407  // variable that refers to n within fn, creating it if necessary.
   408  // Otherwise, it simply returns n.
   409  func CaptureName(pos src.XPos, fn *Func, n *Name) *Name {
   410  	if n.Op() != ONAME || n.Curfn == nil {
   411  		return n // okay to use directly
   412  	}
   413  	if n.IsClosureVar() {
   414  		base.FatalfAt(pos, "misuse of CaptureName on closure variable: %v", n)
   415  	}
   416  
   417  	c := n.Innermost
   418  	if c == nil {
   419  		c = n
   420  	}
   421  	if c.Curfn == fn {
   422  		return c
   423  	}
   424  
   425  	if fn == nil {
   426  		base.FatalfAt(pos, "package-block reference to %v, declared in %v", n, n.Curfn)
   427  	}
   428  
   429  	// Do not have a closure var for the active closure yet; make one.
   430  	c = NewClosureVar(pos, fn, c)
   431  
   432  	// Link into list of active closure variables.
   433  	// Popped from list in FinishCaptureNames.
   434  	n.Innermost = c
   435  
   436  	return c
   437  }
   438  
   439  // FinishCaptureNames handles any work leftover from calling CaptureName
   440  // earlier. outerfn should be the function that immediately encloses fn.
   441  func FinishCaptureNames(pos src.XPos, outerfn, fn *Func) {
   442  	// closure-specific variables are hanging off the
   443  	// ordinary ones; see CaptureName above.
   444  	// unhook them.
   445  	// make the list of pointers for the closure call.
   446  	for _, cv := range fn.ClosureVars {
   447  		// Unlink from n; see comment above on type Name for these fields.
   448  		n := cv.Defn.(*Name)
   449  		n.Innermost = cv.Outer
   450  
   451  		// If the closure usage of n is not dense, we need to make it
   452  		// dense by recapturing n within the enclosing function.
   453  		//
   454  		// That is, suppose we just finished parsing the innermost
   455  		// closure f4 in this code:
   456  		//
   457  		//	func f() {
   458  		//		n := 1
   459  		//		func() { // f2
   460  		//			use(n)
   461  		//			func() { // f3
   462  		//				func() { // f4
   463  		//					use(n)
   464  		//				}()
   465  		//			}()
   466  		//		}()
   467  		//	}
   468  		//
   469  		// At this point cv.Outer is f2's n; there is no n for f3. To
   470  		// construct the closure f4 from within f3, we need to use f3's
   471  		// n and in this case we need to create f3's n with CaptureName.
   472  		//
   473  		// We'll decide later in walk whether to use v directly or &v.
   474  		cv.Outer = CaptureName(pos, outerfn, n)
   475  	}
   476  }
   477  
   478  // SameSource reports whether two nodes refer to the same source
   479  // element.
   480  //
   481  // It exists to help incrementally migrate the compiler towards
   482  // allowing the introduction of IdentExpr (#42990). Once we have
   483  // IdentExpr, it will no longer be safe to directly compare Node
   484  // values to tell if they refer to the same Name. Instead, code will
   485  // need to explicitly get references to the underlying Name object(s),
   486  // and compare those instead.
   487  //
   488  // It will still be safe to compare Nodes directly for checking if two
   489  // nodes are syntactically the same. The SameSource function exists to
   490  // indicate code that intentionally compares Nodes for syntactic
   491  // equality as opposed to code that has yet to be updated in
   492  // preparation for IdentExpr.
   493  func SameSource(n1, n2 Node) bool {
   494  	return n1 == n2
   495  }
   496  
   497  // Uses reports whether expression x is a (direct) use of the given
   498  // variable.
   499  func Uses(x Node, v *Name) bool {
   500  	if v == nil || v.Op() != ONAME {
   501  		base.Fatalf("RefersTo bad Name: %v", v)
   502  	}
   503  	return x.Op() == ONAME && x.Name() == v
   504  }
   505  
   506  // DeclaredBy reports whether expression x refers (directly) to a
   507  // variable that was declared by the given statement.
   508  func DeclaredBy(x, stmt Node) bool {
   509  	if stmt == nil {
   510  		base.Fatalf("DeclaredBy nil")
   511  	}
   512  	return x.Op() == ONAME && SameSource(x.Name().Defn, stmt)
   513  }
   514  
   515  // The Class of a variable/function describes the "storage class"
   516  // of a variable or function. During parsing, storage classes are
   517  // called declaration contexts.
   518  type Class uint8
   519  
   520  //go:generate stringer -type=Class name.go
   521  const (
   522  	Pxxx       Class = iota // no class; used during ssa conversion to indicate pseudo-variables
   523  	PEXTERN                 // global variables
   524  	PAUTO                   // local variables
   525  	PAUTOHEAP               // local variables or parameters moved to heap
   526  	PPARAM                  // input arguments
   527  	PPARAMOUT               // output results
   528  	PTYPEPARAM              // type params
   529  	PFUNC                   // global functions
   530  
   531  	// Careful: Class is stored in three bits in Node.flags.
   532  	_ = uint((1 << 3) - iota) // static assert for iota <= (1 << 3)
   533  )
   534  
   535  type Embed struct {
   536  	Pos      src.XPos
   537  	Patterns []string
   538  }
   539  
   540  // A Pack is an identifier referring to an imported package.
   541  type PkgName struct {
   542  	miniNode
   543  	sym  *types.Sym
   544  	Pkg  *types.Pkg
   545  	Used bool
   546  }
   547  
   548  func (p *PkgName) Sym() *types.Sym { return p.sym }
   549  
   550  func (*PkgName) CanBeNtype() {}
   551  
   552  func NewPkgName(pos src.XPos, sym *types.Sym, pkg *types.Pkg) *PkgName {
   553  	p := &PkgName{sym: sym, Pkg: pkg}
   554  	p.op = OPACK
   555  	p.pos = pos
   556  	return p
   557  }
   558  

View as plain text