Source file src/cmd/compile/internal/ir/func.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/src"
    12  	"fmt"
    13  )
    14  
    15  // A Func corresponds to a single function in a Go program
    16  // (and vice versa: each function is denoted by exactly one *Func).
    17  //
    18  // There are multiple nodes that represent a Func in the IR.
    19  //
    20  // The ONAME node (Func.Nname) is used for plain references to it.
    21  // The ODCLFUNC node (the Func itself) is used for its declaration code.
    22  // The OCLOSURE node (Func.OClosure) is used for a reference to a
    23  // function literal.
    24  //
    25  // An imported function will have an ONAME node which points to a Func
    26  // with an empty body.
    27  // A declared function or method has an ODCLFUNC (the Func itself) and an ONAME.
    28  // A function literal is represented directly by an OCLOSURE, but it also
    29  // has an ODCLFUNC (and a matching ONAME) representing the compiled
    30  // underlying form of the closure, which accesses the captured variables
    31  // using a special data structure passed in a register.
    32  //
    33  // A method declaration is represented like functions, except f.Sym
    34  // will be the qualified method name (e.g., "T.m") and
    35  // f.Func.Shortname is the bare method name (e.g., "m").
    36  //
    37  // A method expression (T.M) is represented as an OMETHEXPR node,
    38  // in which n.Left and n.Right point to the type and method, respectively.
    39  // Each distinct mention of a method expression in the source code
    40  // constructs a fresh node.
    41  //
    42  // A method value (t.M) is represented by ODOTMETH/ODOTINTER
    43  // when it is called directly and by OMETHVALUE otherwise.
    44  // These are like method expressions, except that for ODOTMETH/ODOTINTER,
    45  // the method name is stored in Sym instead of Right.
    46  // Each OMETHVALUE ends up being implemented as a new
    47  // function, a bit like a closure, with its own ODCLFUNC.
    48  // The OMETHVALUE uses n.Func to record the linkage to
    49  // the generated ODCLFUNC, but there is no
    50  // pointer from the Func back to the OMETHVALUE.
    51  type Func struct {
    52  	miniNode
    53  	Body Nodes
    54  	Iota int64
    55  
    56  	Nname    *Name        // ONAME node
    57  	OClosure *ClosureExpr // OCLOSURE node
    58  
    59  	Shortname *types.Sym
    60  
    61  	// Extra entry code for the function. For example, allocate and initialize
    62  	// memory for escaping parameters.
    63  	Enter Nodes
    64  	Exit  Nodes
    65  
    66  	// ONAME nodes for all params/locals for this func/closure, does NOT
    67  	// include closurevars until transforming closures during walk.
    68  	// Names must be listed PPARAMs, PPARAMOUTs, then PAUTOs,
    69  	// with PPARAMs and PPARAMOUTs in order corresponding to the function signature.
    70  	// However, as anonymous or blank PPARAMs are not actually declared,
    71  	// they are omitted from Dcl.
    72  	// Anonymous and blank PPARAMOUTs are declared as ~rNN and ~bNN Names, respectively.
    73  	Dcl []*Name
    74  
    75  	// ClosureVars lists the free variables that are used within a
    76  	// function literal, but formally declared in an enclosing
    77  	// function. The variables in this slice are the closure function's
    78  	// own copy of the variables, which are used within its function
    79  	// body. They will also each have IsClosureVar set, and will have
    80  	// Byval set if they're captured by value.
    81  	ClosureVars []*Name
    82  
    83  	// Enclosed functions that need to be compiled.
    84  	// Populated during walk.
    85  	Closures []*Func
    86  
    87  	// Parents records the parent scope of each scope within a
    88  	// function. The root scope (0) has no parent, so the i'th
    89  	// scope's parent is stored at Parents[i-1].
    90  	Parents []ScopeID
    91  
    92  	// Marks records scope boundary changes.
    93  	Marks []Mark
    94  
    95  	FieldTrack map[*obj.LSym]struct{}
    96  	DebugInfo  interface{}
    97  	LSym       *obj.LSym // Linker object in this function's native ABI (Func.ABI)
    98  
    99  	Inl *Inline
   100  
   101  	// Closgen tracks how many closures have been generated within
   102  	// this function. Used by closurename for creating unique
   103  	// function names.
   104  	Closgen int32
   105  
   106  	Label int32 // largest auto-generated label in this function
   107  
   108  	Endlineno src.XPos
   109  	WBPos     src.XPos // position of first write barrier; see SetWBPos
   110  
   111  	Pragma PragmaFlag // go:xxx function annotations
   112  
   113  	flags bitset16
   114  
   115  	// ABI is a function's "definition" ABI. This is the ABI that
   116  	// this function's generated code is expecting to be called by.
   117  	//
   118  	// For most functions, this will be obj.ABIInternal. It may be
   119  	// a different ABI for functions defined in assembly or ABI wrappers.
   120  	//
   121  	// This is included in the export data and tracked across packages.
   122  	ABI obj.ABI
   123  	// ABIRefs is the set of ABIs by which this function is referenced.
   124  	// For ABIs other than this function's definition ABI, the
   125  	// compiler generates ABI wrapper functions. This is only tracked
   126  	// within a package.
   127  	ABIRefs obj.ABISet
   128  
   129  	NumDefers  int32 // number of defer calls in the function
   130  	NumReturns int32 // number of explicit returns in the function
   131  
   132  	// nwbrCalls records the LSyms of functions called by this
   133  	// function for go:nowritebarrierrec analysis. Only filled in
   134  	// if nowritebarrierrecCheck != nil.
   135  	NWBRCalls *[]SymAndPos
   136  
   137  	// For wrapper functions, WrappedFunc point to the original Func.
   138  	// Currently only used for go/defer wrappers.
   139  	WrappedFunc *Func
   140  }
   141  
   142  func NewFunc(pos src.XPos) *Func {
   143  	f := new(Func)
   144  	f.pos = pos
   145  	f.op = ODCLFUNC
   146  	f.Iota = -1
   147  	// Most functions are ABIInternal. The importer or symabis
   148  	// pass may override this.
   149  	f.ABI = obj.ABIInternal
   150  	return f
   151  }
   152  
   153  func (f *Func) isStmt() {}
   154  
   155  func (n *Func) copy() Node                         { panic(n.no("copy")) }
   156  func (n *Func) doChildren(do func(Node) bool) bool { return doNodes(n.Body, do) }
   157  func (n *Func) editChildren(edit func(Node) Node)  { editNodes(n.Body, edit) }
   158  
   159  func (f *Func) Type() *types.Type                { return f.Nname.Type() }
   160  func (f *Func) Sym() *types.Sym                  { return f.Nname.Sym() }
   161  func (f *Func) Linksym() *obj.LSym               { return f.Nname.Linksym() }
   162  func (f *Func) LinksymABI(abi obj.ABI) *obj.LSym { return f.Nname.LinksymABI(abi) }
   163  
   164  // An Inline holds fields used for function bodies that can be inlined.
   165  type Inline struct {
   166  	Cost int32 // heuristic cost of inlining this function
   167  
   168  	// Copies of Func.Dcl and Func.Body for use during inlining. Copies are
   169  	// needed because the function's dcl/body may be changed by later compiler
   170  	// transformations. These fields are also populated when a function from
   171  	// another package is imported.
   172  	Dcl  []*Name
   173  	Body []Node
   174  
   175  	// CanDelayResults reports whether it's safe for the inliner to delay
   176  	// initializing the result parameters until immediately before the
   177  	// "return" statement.
   178  	CanDelayResults bool
   179  }
   180  
   181  // A Mark represents a scope boundary.
   182  type Mark struct {
   183  	// Pos is the position of the token that marks the scope
   184  	// change.
   185  	Pos src.XPos
   186  
   187  	// Scope identifies the innermost scope to the right of Pos.
   188  	Scope ScopeID
   189  }
   190  
   191  // A ScopeID represents a lexical scope within a function.
   192  type ScopeID int32
   193  
   194  const (
   195  	funcDupok         = 1 << iota // duplicate definitions ok
   196  	funcWrapper                   // hide frame from users (elide in tracebacks, don't count as a frame for recover())
   197  	funcABIWrapper                // is an ABI wrapper (also set flagWrapper)
   198  	funcNeedctxt                  // function uses context register (has closure variables)
   199  	funcReflectMethod             // function calls reflect.Type.Method or MethodByName
   200  	// true if closure inside a function; false if a simple function or a
   201  	// closure in a global variable initialization
   202  	funcIsHiddenClosure
   203  	funcIsDeadcodeClosure        // true if closure is deadcode
   204  	funcHasDefer                 // contains a defer statement
   205  	funcNilCheckDisabled         // disable nil checks when compiling this function
   206  	funcInlinabilityChecked      // inliner has already determined whether the function is inlinable
   207  	funcExportInline             // include inline body in export data
   208  	funcInstrumentBody           // add race/msan/asan instrumentation during SSA construction
   209  	funcOpenCodedDeferDisallowed // can't do open-coded defers
   210  	funcClosureCalled            // closure is only immediately called; used by escape analysis
   211  )
   212  
   213  type SymAndPos struct {
   214  	Sym *obj.LSym // LSym of callee
   215  	Pos src.XPos  // line of call
   216  }
   217  
   218  func (f *Func) Dupok() bool                    { return f.flags&funcDupok != 0 }
   219  func (f *Func) Wrapper() bool                  { return f.flags&funcWrapper != 0 }
   220  func (f *Func) ABIWrapper() bool               { return f.flags&funcABIWrapper != 0 }
   221  func (f *Func) Needctxt() bool                 { return f.flags&funcNeedctxt != 0 }
   222  func (f *Func) ReflectMethod() bool            { return f.flags&funcReflectMethod != 0 }
   223  func (f *Func) IsHiddenClosure() bool          { return f.flags&funcIsHiddenClosure != 0 }
   224  func (f *Func) IsDeadcodeClosure() bool        { return f.flags&funcIsDeadcodeClosure != 0 }
   225  func (f *Func) HasDefer() bool                 { return f.flags&funcHasDefer != 0 }
   226  func (f *Func) NilCheckDisabled() bool         { return f.flags&funcNilCheckDisabled != 0 }
   227  func (f *Func) InlinabilityChecked() bool      { return f.flags&funcInlinabilityChecked != 0 }
   228  func (f *Func) ExportInline() bool             { return f.flags&funcExportInline != 0 }
   229  func (f *Func) InstrumentBody() bool           { return f.flags&funcInstrumentBody != 0 }
   230  func (f *Func) OpenCodedDeferDisallowed() bool { return f.flags&funcOpenCodedDeferDisallowed != 0 }
   231  func (f *Func) ClosureCalled() bool            { return f.flags&funcClosureCalled != 0 }
   232  
   233  func (f *Func) SetDupok(b bool)                    { f.flags.set(funcDupok, b) }
   234  func (f *Func) SetWrapper(b bool)                  { f.flags.set(funcWrapper, b) }
   235  func (f *Func) SetABIWrapper(b bool)               { f.flags.set(funcABIWrapper, b) }
   236  func (f *Func) SetNeedctxt(b bool)                 { f.flags.set(funcNeedctxt, b) }
   237  func (f *Func) SetReflectMethod(b bool)            { f.flags.set(funcReflectMethod, b) }
   238  func (f *Func) SetIsHiddenClosure(b bool)          { f.flags.set(funcIsHiddenClosure, b) }
   239  func (f *Func) SetIsDeadcodeClosure(b bool)        { f.flags.set(funcIsDeadcodeClosure, b) }
   240  func (f *Func) SetHasDefer(b bool)                 { f.flags.set(funcHasDefer, b) }
   241  func (f *Func) SetNilCheckDisabled(b bool)         { f.flags.set(funcNilCheckDisabled, b) }
   242  func (f *Func) SetInlinabilityChecked(b bool)      { f.flags.set(funcInlinabilityChecked, b) }
   243  func (f *Func) SetExportInline(b bool)             { f.flags.set(funcExportInline, b) }
   244  func (f *Func) SetInstrumentBody(b bool)           { f.flags.set(funcInstrumentBody, b) }
   245  func (f *Func) SetOpenCodedDeferDisallowed(b bool) { f.flags.set(funcOpenCodedDeferDisallowed, b) }
   246  func (f *Func) SetClosureCalled(b bool)            { f.flags.set(funcClosureCalled, b) }
   247  
   248  func (f *Func) SetWBPos(pos src.XPos) {
   249  	if base.Debug.WB != 0 {
   250  		base.WarnfAt(pos, "write barrier")
   251  	}
   252  	if !f.WBPos.IsKnown() {
   253  		f.WBPos = pos
   254  	}
   255  }
   256  
   257  // FuncName returns the name (without the package) of the function n.
   258  func FuncName(f *Func) string {
   259  	if f == nil || f.Nname == nil {
   260  		return "<nil>"
   261  	}
   262  	return f.Sym().Name
   263  }
   264  
   265  // PkgFuncName returns the name of the function referenced by n, with package prepended.
   266  // This differs from the compiler's internal convention where local functions lack a package
   267  // because the ultimate consumer of this is a human looking at an IDE; package is only empty
   268  // if the compilation package is actually the empty string.
   269  func PkgFuncName(f *Func) string {
   270  	if f == nil || f.Nname == nil {
   271  		return "<nil>"
   272  	}
   273  	s := f.Sym()
   274  	pkg := s.Pkg
   275  
   276  	p := base.Ctxt.Pkgpath
   277  	if pkg != nil && pkg.Path != "" {
   278  		p = pkg.Path
   279  	}
   280  	if p == "" {
   281  		return s.Name
   282  	}
   283  	return p + "." + s.Name
   284  }
   285  
   286  var CurFunc *Func
   287  
   288  // WithFunc invokes do with CurFunc and base.Pos set to curfn and
   289  // curfn.Pos(), respectively, and then restores their previous values
   290  // before returning.
   291  func WithFunc(curfn *Func, do func()) {
   292  	oldfn, oldpos := CurFunc, base.Pos
   293  	defer func() { CurFunc, base.Pos = oldfn, oldpos }()
   294  
   295  	CurFunc, base.Pos = curfn, curfn.Pos()
   296  	do()
   297  }
   298  
   299  func FuncSymName(s *types.Sym) string {
   300  	return s.Name + "·f"
   301  }
   302  
   303  // MarkFunc marks a node as a function.
   304  func MarkFunc(n *Name) {
   305  	if n.Op() != ONAME || n.Class != Pxxx {
   306  		base.FatalfAt(n.Pos(), "expected ONAME/Pxxx node, got %v (%v/%v)", n, n.Op(), n.Class)
   307  	}
   308  
   309  	n.Class = PFUNC
   310  	n.Sym().SetFunc(true)
   311  }
   312  
   313  // ClosureDebugRuntimeCheck applies boilerplate checks for debug flags
   314  // and compiling runtime
   315  func ClosureDebugRuntimeCheck(clo *ClosureExpr) {
   316  	if base.Debug.Closure > 0 {
   317  		if clo.Esc() == EscHeap {
   318  			base.WarnfAt(clo.Pos(), "heap closure, captured vars = %v", clo.Func.ClosureVars)
   319  		} else {
   320  			base.WarnfAt(clo.Pos(), "stack closure, captured vars = %v", clo.Func.ClosureVars)
   321  		}
   322  	}
   323  	if base.Flag.CompilingRuntime && clo.Esc() == EscHeap && !clo.IsGoWrap {
   324  		base.ErrorfAt(clo.Pos(), "heap-allocated closure %s, not allowed in runtime", FuncName(clo.Func))
   325  	}
   326  }
   327  
   328  // IsTrivialClosure reports whether closure clo has an
   329  // empty list of captured vars.
   330  func IsTrivialClosure(clo *ClosureExpr) bool {
   331  	return len(clo.Func.ClosureVars) == 0
   332  }
   333  
   334  // globClosgen is like Func.Closgen, but for the global scope.
   335  var globClosgen int32
   336  
   337  // closureName generates a new unique name for a closure within outerfn.
   338  func closureName(outerfn *Func) *types.Sym {
   339  	pkg := types.LocalPkg
   340  	outer := "glob."
   341  	prefix := "func"
   342  	gen := &globClosgen
   343  
   344  	if outerfn != nil {
   345  		if outerfn.OClosure != nil {
   346  			prefix = ""
   347  		}
   348  
   349  		pkg = outerfn.Sym().Pkg
   350  		outer = FuncName(outerfn)
   351  
   352  		// There may be multiple functions named "_". In those
   353  		// cases, we can't use their individual Closgens as it
   354  		// would lead to name clashes.
   355  		if !IsBlank(outerfn.Nname) {
   356  			gen = &outerfn.Closgen
   357  		}
   358  	}
   359  
   360  	*gen++
   361  	return pkg.Lookup(fmt.Sprintf("%s.%s%d", outer, prefix, *gen))
   362  }
   363  
   364  // NewClosureFunc creates a new Func to represent a function literal.
   365  // If hidden is true, then the closure is marked hidden (i.e., as a
   366  // function literal contained within another function, rather than a
   367  // package-scope variable initialization expression).
   368  func NewClosureFunc(pos src.XPos, hidden bool) *Func {
   369  	fn := NewFunc(pos)
   370  	fn.SetIsHiddenClosure(hidden)
   371  
   372  	fn.Nname = NewNameAt(pos, BlankNode.Sym())
   373  	fn.Nname.Func = fn
   374  	fn.Nname.Defn = fn
   375  
   376  	fn.OClosure = NewClosureExpr(pos, fn)
   377  
   378  	return fn
   379  }
   380  
   381  // NameClosure generates a unique for the given function literal,
   382  // which must have appeared within outerfn.
   383  func NameClosure(clo *ClosureExpr, outerfn *Func) {
   384  	fn := clo.Func
   385  	if fn.IsHiddenClosure() != (outerfn != nil) {
   386  		base.FatalfAt(clo.Pos(), "closure naming inconsistency: hidden %v, but outer %v", fn.IsHiddenClosure(), outerfn)
   387  	}
   388  
   389  	name := fn.Nname
   390  	if !IsBlank(name) {
   391  		base.FatalfAt(clo.Pos(), "closure already named: %v", name)
   392  	}
   393  
   394  	name.SetSym(closureName(outerfn))
   395  	MarkFunc(name)
   396  }
   397  
   398  // UseClosure checks that the ginen function literal has been setup
   399  // correctly, and then returns it as an expression.
   400  // It must be called after clo.Func.ClosureVars has been set.
   401  func UseClosure(clo *ClosureExpr, pkg *Package) Node {
   402  	fn := clo.Func
   403  	name := fn.Nname
   404  
   405  	if IsBlank(name) {
   406  		base.FatalfAt(fn.Pos(), "unnamed closure func: %v", fn)
   407  	}
   408  	// Caution: clo.Typecheck() is still 0 when UseClosure is called by
   409  	// tcClosure.
   410  	if fn.Typecheck() != 1 || name.Typecheck() != 1 {
   411  		base.FatalfAt(fn.Pos(), "missed typecheck: %v", fn)
   412  	}
   413  	if clo.Type() == nil || name.Type() == nil {
   414  		base.FatalfAt(fn.Pos(), "missing types: %v", fn)
   415  	}
   416  	if !types.Identical(clo.Type(), name.Type()) {
   417  		base.FatalfAt(fn.Pos(), "mismatched types: %v", fn)
   418  	}
   419  
   420  	if base.Flag.W > 1 {
   421  		s := fmt.Sprintf("new closure func: %v", fn)
   422  		Dump(s, fn)
   423  	}
   424  
   425  	if pkg != nil {
   426  		pkg.Decls = append(pkg.Decls, fn)
   427  	}
   428  
   429  	if false && IsTrivialClosure(clo) {
   430  		// TODO(mdempsky): Investigate if we can/should optimize this
   431  		// case. walkClosure already handles it later, but it could be
   432  		// useful to recognize earlier (e.g., it might allow multiple
   433  		// inlined calls to a function to share a common trivial closure
   434  		// func, rather than cloning it for each inlined call).
   435  	}
   436  
   437  	return clo
   438  }
   439  

View as plain text