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/objabi"
    12  	"cmd/internal/src"
    13  	"fmt"
    14  	"strings"
    15  	"unicode/utf8"
    16  )
    17  
    18  // A Func corresponds to a single function in a Go program
    19  // (and vice versa: each function is denoted by exactly one *Func).
    20  //
    21  // There are multiple nodes that represent a Func in the IR.
    22  //
    23  // The ONAME node (Func.Nname) is used for plain references to it.
    24  // The ODCLFUNC node (the Func itself) is used for its declaration code.
    25  // The OCLOSURE node (Func.OClosure) is used for a reference to a
    26  // function literal.
    27  //
    28  // An imported function will have an ONAME node which points to a Func
    29  // with an empty body.
    30  // A declared function or method has an ODCLFUNC (the Func itself) and an ONAME.
    31  // A function literal is represented directly by an OCLOSURE, but it also
    32  // has an ODCLFUNC (and a matching ONAME) representing the compiled
    33  // underlying form of the closure, which accesses the captured variables
    34  // using a special data structure passed in a register.
    35  //
    36  // A method declaration is represented like functions, except f.Sym
    37  // will be the qualified method name (e.g., "T.m").
    38  //
    39  // A method expression (T.M) is represented as an OMETHEXPR node,
    40  // in which n.Left and n.Right point to the type and method, respectively.
    41  // Each distinct mention of a method expression in the source code
    42  // constructs a fresh node.
    43  //
    44  // A method value (t.M) is represented by ODOTMETH/ODOTINTER
    45  // when it is called directly and by OMETHVALUE otherwise.
    46  // These are like method expressions, except that for ODOTMETH/ODOTINTER,
    47  // the method name is stored in Sym instead of Right.
    48  // Each OMETHVALUE ends up being implemented as a new
    49  // function, a bit like a closure, with its own ODCLFUNC.
    50  // The OMETHVALUE uses n.Func to record the linkage to
    51  // the generated ODCLFUNC, but there is no
    52  // pointer from the Func back to the OMETHVALUE.
    53  type Func struct {
    54  	miniNode
    55  	Body Nodes
    56  
    57  	Nname    *Name        // ONAME node
    58  	OClosure *ClosureExpr // OCLOSURE node
    59  
    60  	// ONAME nodes for all params/locals for this func/closure, does NOT
    61  	// include closurevars until transforming closures during walk.
    62  	// Names must be listed PPARAMs, PPARAMOUTs, then PAUTOs,
    63  	// with PPARAMs and PPARAMOUTs in order corresponding to the function signature.
    64  	// Anonymous and blank params are declared as ~pNN (for PPARAMs) and ~rNN (for PPARAMOUTs).
    65  	Dcl []*Name
    66  
    67  	// ClosureVars lists the free variables that are used within a
    68  	// function literal, but formally declared in an enclosing
    69  	// function. The variables in this slice are the closure function's
    70  	// own copy of the variables, which are used within its function
    71  	// body. They will also each have IsClosureVar set, and will have
    72  	// Byval set if they're captured by value.
    73  	ClosureVars []*Name
    74  
    75  	// Enclosed functions that need to be compiled.
    76  	// Populated during walk.
    77  	Closures []*Func
    78  
    79  	// Parents records the parent scope of each scope within a
    80  	// function. The root scope (0) has no parent, so the i'th
    81  	// scope's parent is stored at Parents[i-1].
    82  	Parents []ScopeID
    83  
    84  	// Marks records scope boundary changes.
    85  	Marks []Mark
    86  
    87  	FieldTrack map[*obj.LSym]struct{}
    88  	DebugInfo  interface{}
    89  	LSym       *obj.LSym // Linker object in this function's native ABI (Func.ABI)
    90  
    91  	Inl *Inline
    92  
    93  	// funcLitGen and goDeferGen track how many closures have been
    94  	// created in this function for function literals and go/defer
    95  	// wrappers, respectively. Used by closureName for creating unique
    96  	// function names.
    97  	//
    98  	// Tracking goDeferGen separately avoids wrappers throwing off
    99  	// function literal numbering (e.g., runtime/trace_test.TestTraceSymbolize.func11).
   100  	funcLitGen int32
   101  	goDeferGen int32
   102  
   103  	Label int32 // largest auto-generated label in this function
   104  
   105  	Endlineno src.XPos
   106  	WBPos     src.XPos // position of first write barrier; see SetWBPos
   107  
   108  	Pragma PragmaFlag // go:xxx function annotations
   109  
   110  	flags bitset16
   111  
   112  	// ABI is a function's "definition" ABI. This is the ABI that
   113  	// this function's generated code is expecting to be called by.
   114  	//
   115  	// For most functions, this will be obj.ABIInternal. It may be
   116  	// a different ABI for functions defined in assembly or ABI wrappers.
   117  	//
   118  	// This is included in the export data and tracked across packages.
   119  	ABI obj.ABI
   120  	// ABIRefs is the set of ABIs by which this function is referenced.
   121  	// For ABIs other than this function's definition ABI, the
   122  	// compiler generates ABI wrapper functions. This is only tracked
   123  	// within a package.
   124  	ABIRefs obj.ABISet
   125  
   126  	NumDefers  int32 // number of defer calls in the function
   127  	NumReturns int32 // number of explicit returns in the function
   128  
   129  	// NWBRCalls records the LSyms of functions called by this
   130  	// function for go:nowritebarrierrec analysis. Only filled in
   131  	// if nowritebarrierrecCheck != nil.
   132  	NWBRCalls *[]SymAndPos
   133  
   134  	// For wrapper functions, WrappedFunc point to the original Func.
   135  	// Currently only used for go/defer wrappers.
   136  	WrappedFunc *Func
   137  
   138  	// WasmImport is used by the //go:wasmimport directive to store info about
   139  	// a WebAssembly function import.
   140  	WasmImport *WasmImport
   141  }
   142  
   143  // WasmImport stores metadata associated with the //go:wasmimport pragma.
   144  type WasmImport struct {
   145  	Module string
   146  	Name   string
   147  }
   148  
   149  // NewFunc returns a new Func with the given name and type.
   150  //
   151  // fpos is the position of the "func" token, and npos is the position
   152  // of the name identifier.
   153  //
   154  // TODO(mdempsky): I suspect there's no need for separate fpos and
   155  // npos.
   156  func NewFunc(fpos, npos src.XPos, sym *types.Sym, typ *types.Type) *Func {
   157  	name := NewNameAt(npos, sym, typ)
   158  	name.Class = PFUNC
   159  	sym.SetFunc(true)
   160  
   161  	fn := &Func{Nname: name}
   162  	fn.pos = fpos
   163  	fn.op = ODCLFUNC
   164  	// Most functions are ABIInternal. The importer or symabis
   165  	// pass may override this.
   166  	fn.ABI = obj.ABIInternal
   167  	fn.SetTypecheck(1)
   168  
   169  	name.Func = fn
   170  
   171  	return fn
   172  }
   173  
   174  func (f *Func) isStmt() {}
   175  
   176  func (n *Func) copy() Node                                  { panic(n.no("copy")) }
   177  func (n *Func) doChildren(do func(Node) bool) bool          { return doNodes(n.Body, do) }
   178  func (n *Func) editChildren(edit func(Node) Node)           { editNodes(n.Body, edit) }
   179  func (n *Func) editChildrenWithHidden(edit func(Node) Node) { editNodes(n.Body, edit) }
   180  
   181  func (f *Func) Type() *types.Type                { return f.Nname.Type() }
   182  func (f *Func) Sym() *types.Sym                  { return f.Nname.Sym() }
   183  func (f *Func) Linksym() *obj.LSym               { return f.Nname.Linksym() }
   184  func (f *Func) LinksymABI(abi obj.ABI) *obj.LSym { return f.Nname.LinksymABI(abi) }
   185  
   186  // An Inline holds fields used for function bodies that can be inlined.
   187  type Inline struct {
   188  	Cost int32 // heuristic cost of inlining this function
   189  
   190  	// Copy of Func.Dcl for use during inlining. This copy is needed
   191  	// because the function's Dcl may change from later compiler
   192  	// transformations. This field is also populated when a function
   193  	// from another package is imported and inlined.
   194  	Dcl     []*Name
   195  	HaveDcl bool // whether we've loaded Dcl
   196  
   197  	// Function properties, encoded as a string (these are used for
   198  	// making inlining decisions). See cmd/compile/internal/inline/inlheur.
   199  	Properties string
   200  
   201  	// CanDelayResults reports whether it's safe for the inliner to delay
   202  	// initializing the result parameters until immediately before the
   203  	// "return" statement.
   204  	CanDelayResults bool
   205  }
   206  
   207  // A Mark represents a scope boundary.
   208  type Mark struct {
   209  	// Pos is the position of the token that marks the scope
   210  	// change.
   211  	Pos src.XPos
   212  
   213  	// Scope identifies the innermost scope to the right of Pos.
   214  	Scope ScopeID
   215  }
   216  
   217  // A ScopeID represents a lexical scope within a function.
   218  type ScopeID int32
   219  
   220  const (
   221  	funcDupok      = 1 << iota // duplicate definitions ok
   222  	funcWrapper                // hide frame from users (elide in tracebacks, don't count as a frame for recover())
   223  	funcABIWrapper             // is an ABI wrapper (also set flagWrapper)
   224  	funcNeedctxt               // function uses context register (has closure variables)
   225  	// true if closure inside a function; false if a simple function or a
   226  	// closure in a global variable initialization
   227  	funcIsHiddenClosure
   228  	funcIsDeadcodeClosure        // true if closure is deadcode
   229  	funcHasDefer                 // contains a defer statement
   230  	funcNilCheckDisabled         // disable nil checks when compiling this function
   231  	funcInlinabilityChecked      // inliner has already determined whether the function is inlinable
   232  	funcNeverReturns             // function never returns (in most cases calls panic(), os.Exit(), or equivalent)
   233  	funcOpenCodedDeferDisallowed // can't do open-coded defers
   234  	funcClosureResultsLost       // closure is called indirectly and we lost track of its results; used by escape analysis
   235  	funcPackageInit              // compiler emitted .init func for package
   236  )
   237  
   238  type SymAndPos struct {
   239  	Sym *obj.LSym // LSym of callee
   240  	Pos src.XPos  // line of call
   241  }
   242  
   243  func (f *Func) Dupok() bool                    { return f.flags&funcDupok != 0 }
   244  func (f *Func) Wrapper() bool                  { return f.flags&funcWrapper != 0 }
   245  func (f *Func) ABIWrapper() bool               { return f.flags&funcABIWrapper != 0 }
   246  func (f *Func) Needctxt() bool                 { return f.flags&funcNeedctxt != 0 }
   247  func (f *Func) IsHiddenClosure() bool          { return f.flags&funcIsHiddenClosure != 0 }
   248  func (f *Func) IsDeadcodeClosure() bool        { return f.flags&funcIsDeadcodeClosure != 0 }
   249  func (f *Func) HasDefer() bool                 { return f.flags&funcHasDefer != 0 }
   250  func (f *Func) NilCheckDisabled() bool         { return f.flags&funcNilCheckDisabled != 0 }
   251  func (f *Func) InlinabilityChecked() bool      { return f.flags&funcInlinabilityChecked != 0 }
   252  func (f *Func) NeverReturns() bool             { return f.flags&funcNeverReturns != 0 }
   253  func (f *Func) OpenCodedDeferDisallowed() bool { return f.flags&funcOpenCodedDeferDisallowed != 0 }
   254  func (f *Func) ClosureResultsLost() bool       { return f.flags&funcClosureResultsLost != 0 }
   255  func (f *Func) IsPackageInit() bool            { return f.flags&funcPackageInit != 0 }
   256  
   257  func (f *Func) SetDupok(b bool)                    { f.flags.set(funcDupok, b) }
   258  func (f *Func) SetWrapper(b bool)                  { f.flags.set(funcWrapper, b) }
   259  func (f *Func) SetABIWrapper(b bool)               { f.flags.set(funcABIWrapper, b) }
   260  func (f *Func) SetNeedctxt(b bool)                 { f.flags.set(funcNeedctxt, b) }
   261  func (f *Func) SetIsHiddenClosure(b bool)          { f.flags.set(funcIsHiddenClosure, b) }
   262  func (f *Func) SetIsDeadcodeClosure(b bool)        { f.flags.set(funcIsDeadcodeClosure, b) }
   263  func (f *Func) SetHasDefer(b bool)                 { f.flags.set(funcHasDefer, b) }
   264  func (f *Func) SetNilCheckDisabled(b bool)         { f.flags.set(funcNilCheckDisabled, b) }
   265  func (f *Func) SetInlinabilityChecked(b bool)      { f.flags.set(funcInlinabilityChecked, b) }
   266  func (f *Func) SetNeverReturns(b bool)             { f.flags.set(funcNeverReturns, b) }
   267  func (f *Func) SetOpenCodedDeferDisallowed(b bool) { f.flags.set(funcOpenCodedDeferDisallowed, b) }
   268  func (f *Func) SetClosureResultsLost(b bool)       { f.flags.set(funcClosureResultsLost, b) }
   269  func (f *Func) SetIsPackageInit(b bool)            { f.flags.set(funcPackageInit, b) }
   270  
   271  func (f *Func) SetWBPos(pos src.XPos) {
   272  	if base.Debug.WB != 0 {
   273  		base.WarnfAt(pos, "write barrier")
   274  	}
   275  	if !f.WBPos.IsKnown() {
   276  		f.WBPos = pos
   277  	}
   278  }
   279  
   280  // FuncName returns the name (without the package) of the function f.
   281  func FuncName(f *Func) string {
   282  	if f == nil || f.Nname == nil {
   283  		return "<nil>"
   284  	}
   285  	return f.Sym().Name
   286  }
   287  
   288  // PkgFuncName returns the name of the function referenced by f, with package
   289  // prepended.
   290  //
   291  // This differs from the compiler's internal convention where local functions
   292  // lack a package. This is primarily useful when the ultimate consumer of this
   293  // is a human looking at message.
   294  func PkgFuncName(f *Func) string {
   295  	if f == nil || f.Nname == nil {
   296  		return "<nil>"
   297  	}
   298  	s := f.Sym()
   299  	pkg := s.Pkg
   300  
   301  	return pkg.Path + "." + s.Name
   302  }
   303  
   304  // LinkFuncName returns the name of the function f, as it will appear in the
   305  // symbol table of the final linked binary.
   306  func LinkFuncName(f *Func) string {
   307  	if f == nil || f.Nname == nil {
   308  		return "<nil>"
   309  	}
   310  	s := f.Sym()
   311  	pkg := s.Pkg
   312  
   313  	return objabi.PathToPrefix(pkg.Path) + "." + s.Name
   314  }
   315  
   316  // ParseLinkFuncName parsers a symbol name (as returned from LinkFuncName) back
   317  // to the package path and local symbol name.
   318  func ParseLinkFuncName(name string) (pkg, sym string, err error) {
   319  	pkg, sym = splitPkg(name)
   320  	if pkg == "" {
   321  		return "", "", fmt.Errorf("no package path in name")
   322  	}
   323  
   324  	pkg, err = objabi.PrefixToPath(pkg) // unescape
   325  	if err != nil {
   326  		return "", "", fmt.Errorf("malformed package path: %v", err)
   327  	}
   328  
   329  	return pkg, sym, nil
   330  }
   331  
   332  // Borrowed from x/mod.
   333  func modPathOK(r rune) bool {
   334  	if r < utf8.RuneSelf {
   335  		return r == '-' || r == '.' || r == '_' || r == '~' ||
   336  			'0' <= r && r <= '9' ||
   337  			'A' <= r && r <= 'Z' ||
   338  			'a' <= r && r <= 'z'
   339  	}
   340  	return false
   341  }
   342  
   343  func escapedImportPathOK(r rune) bool {
   344  	return modPathOK(r) || r == '+' || r == '/' || r == '%'
   345  }
   346  
   347  // splitPkg splits the full linker symbol name into package and local symbol
   348  // name.
   349  func splitPkg(name string) (pkgpath, sym string) {
   350  	// package-sym split is at first dot after last the / that comes before
   351  	// any characters illegal in a package path.
   352  
   353  	lastSlashIdx := 0
   354  	for i, r := range name {
   355  		// Catches cases like:
   356  		// * example.foo[sync/atomic.Uint64].
   357  		// * example%2ecom.foo[sync/atomic.Uint64].
   358  		//
   359  		// Note that name is still escaped; unescape occurs after splitPkg.
   360  		if !escapedImportPathOK(r) {
   361  			break
   362  		}
   363  		if r == '/' {
   364  			lastSlashIdx = i
   365  		}
   366  	}
   367  	for i := lastSlashIdx; i < len(name); i++ {
   368  		r := name[i]
   369  		if r == '.' {
   370  			return name[:i], name[i+1:]
   371  		}
   372  	}
   373  
   374  	return "", name
   375  }
   376  
   377  var CurFunc *Func
   378  
   379  // WithFunc invokes do with CurFunc and base.Pos set to curfn and
   380  // curfn.Pos(), respectively, and then restores their previous values
   381  // before returning.
   382  func WithFunc(curfn *Func, do func()) {
   383  	oldfn, oldpos := CurFunc, base.Pos
   384  	defer func() { CurFunc, base.Pos = oldfn, oldpos }()
   385  
   386  	CurFunc, base.Pos = curfn, curfn.Pos()
   387  	do()
   388  }
   389  
   390  func FuncSymName(s *types.Sym) string {
   391  	return s.Name + "·f"
   392  }
   393  
   394  // ClosureDebugRuntimeCheck applies boilerplate checks for debug flags
   395  // and compiling runtime.
   396  func ClosureDebugRuntimeCheck(clo *ClosureExpr) {
   397  	if base.Debug.Closure > 0 {
   398  		if clo.Esc() == EscHeap {
   399  			base.WarnfAt(clo.Pos(), "heap closure, captured vars = %v", clo.Func.ClosureVars)
   400  		} else {
   401  			base.WarnfAt(clo.Pos(), "stack closure, captured vars = %v", clo.Func.ClosureVars)
   402  		}
   403  	}
   404  	if base.Flag.CompilingRuntime && clo.Esc() == EscHeap && !clo.IsGoWrap {
   405  		base.ErrorfAt(clo.Pos(), 0, "heap-allocated closure %s, not allowed in runtime", FuncName(clo.Func))
   406  	}
   407  }
   408  
   409  // IsTrivialClosure reports whether closure clo has an
   410  // empty list of captured vars.
   411  func IsTrivialClosure(clo *ClosureExpr) bool {
   412  	return len(clo.Func.ClosureVars) == 0
   413  }
   414  
   415  // globClosgen is like Func.Closgen, but for the global scope.
   416  var globClosgen int32
   417  
   418  // closureName generates a new unique name for a closure within outerfn at pos.
   419  func closureName(outerfn *Func, pos src.XPos, why Op) *types.Sym {
   420  	pkg := types.LocalPkg
   421  	outer := "glob."
   422  	var prefix string
   423  	switch why {
   424  	default:
   425  		base.FatalfAt(pos, "closureName: bad Op: %v", why)
   426  	case OCLOSURE:
   427  		if outerfn == nil || outerfn.OClosure == nil {
   428  			prefix = "func"
   429  		}
   430  	case OGO:
   431  		prefix = "gowrap"
   432  	case ODEFER:
   433  		prefix = "deferwrap"
   434  	}
   435  	gen := &globClosgen
   436  
   437  	// There may be multiple functions named "_". In those
   438  	// cases, we can't use their individual Closgens as it
   439  	// would lead to name clashes.
   440  	if outerfn != nil && !IsBlank(outerfn.Nname) {
   441  		pkg = outerfn.Sym().Pkg
   442  		outer = FuncName(outerfn)
   443  
   444  		if why == OCLOSURE {
   445  			gen = &outerfn.funcLitGen
   446  		} else {
   447  			gen = &outerfn.goDeferGen
   448  		}
   449  	}
   450  
   451  	// If this closure was created due to inlining, then incorporate any
   452  	// inlined functions' names into the closure's linker symbol name
   453  	// too (#60324).
   454  	if inlIndex := base.Ctxt.InnermostPos(pos).Base().InliningIndex(); inlIndex >= 0 {
   455  		names := []string{outer}
   456  		base.Ctxt.InlTree.AllParents(inlIndex, func(call obj.InlinedCall) {
   457  			names = append(names, call.Name)
   458  		})
   459  		outer = strings.Join(names, ".")
   460  	}
   461  
   462  	*gen++
   463  	return pkg.Lookup(fmt.Sprintf("%s.%s%d", outer, prefix, *gen))
   464  }
   465  
   466  // NewClosureFunc creates a new Func to represent a function literal
   467  // with the given type.
   468  //
   469  // fpos the position used for the underlying ODCLFUNC and ONAME,
   470  // whereas cpos is the position used for the OCLOSURE. They're
   471  // separate because in the presence of inlining, the OCLOSURE node
   472  // should have an inline-adjusted position, whereas the ODCLFUNC and
   473  // ONAME must not.
   474  //
   475  // outerfn is the enclosing function, if any. The returned function is
   476  // appending to pkg.Funcs.
   477  //
   478  // why is the reason we're generating this Func. It can be OCLOSURE
   479  // (for a normal function literal) or OGO or ODEFER (for wrapping a
   480  // call expression that has parameters or results).
   481  func NewClosureFunc(fpos, cpos src.XPos, why Op, typ *types.Type, outerfn *Func, pkg *Package) *Func {
   482  	fn := NewFunc(fpos, fpos, closureName(outerfn, cpos, why), typ)
   483  	fn.SetIsHiddenClosure(outerfn != nil)
   484  
   485  	clo := &ClosureExpr{Func: fn}
   486  	clo.op = OCLOSURE
   487  	clo.pos = cpos
   488  	clo.SetType(typ)
   489  	clo.SetTypecheck(1)
   490  	fn.OClosure = clo
   491  
   492  	fn.Nname.Defn = fn
   493  	pkg.Funcs = append(pkg.Funcs, fn)
   494  
   495  	return fn
   496  }
   497  
   498  // IsFuncPCIntrinsic returns whether n is a direct call of internal/abi.FuncPCABIxxx functions.
   499  func IsFuncPCIntrinsic(n *CallExpr) bool {
   500  	if n.Op() != OCALLFUNC || n.Fun.Op() != ONAME {
   501  		return false
   502  	}
   503  	fn := n.Fun.(*Name).Sym()
   504  	return (fn.Name == "FuncPCABI0" || fn.Name == "FuncPCABIInternal") &&
   505  		fn.Pkg.Path == "internal/abi"
   506  }
   507  
   508  // IsIfaceOfFunc inspects whether n is an interface conversion from a direct
   509  // reference of a func. If so, it returns referenced Func; otherwise nil.
   510  //
   511  // This is only usable before walk.walkConvertInterface, which converts to an
   512  // OMAKEFACE.
   513  func IsIfaceOfFunc(n Node) *Func {
   514  	if n, ok := n.(*ConvExpr); ok && n.Op() == OCONVIFACE {
   515  		if name, ok := n.X.(*Name); ok && name.Op() == ONAME && name.Class == PFUNC {
   516  			return name.Func
   517  		}
   518  	}
   519  	return nil
   520  }
   521  
   522  // FuncPC returns a uintptr-typed expression that evaluates to the PC of a
   523  // function as uintptr, as returned by internal/abi.FuncPC{ABI0,ABIInternal}.
   524  //
   525  // n should be a Node of an interface type, as is passed to
   526  // internal/abi.FuncPC{ABI0,ABIInternal}.
   527  //
   528  // TODO(prattmic): Since n is simply an interface{} there is no assertion that
   529  // it is actually a function at all. Perhaps we should emit a runtime type
   530  // assertion?
   531  func FuncPC(pos src.XPos, n Node, wantABI obj.ABI) Node {
   532  	if !n.Type().IsInterface() {
   533  		base.ErrorfAt(pos, 0, "internal/abi.FuncPC%s expects an interface value, got %v", wantABI, n.Type())
   534  	}
   535  
   536  	if fn := IsIfaceOfFunc(n); fn != nil {
   537  		name := fn.Nname
   538  		abi := fn.ABI
   539  		if abi != wantABI {
   540  			base.ErrorfAt(pos, 0, "internal/abi.FuncPC%s expects an %v function, %s is defined as %v", wantABI, wantABI, name.Sym().Name, abi)
   541  		}
   542  		var e Node = NewLinksymExpr(pos, name.Sym().LinksymABI(abi), types.Types[types.TUINTPTR])
   543  		e = NewAddrExpr(pos, e)
   544  		e.SetType(types.Types[types.TUINTPTR].PtrTo())
   545  		e = NewConvExpr(pos, OCONVNOP, types.Types[types.TUINTPTR], e)
   546  		e.SetTypecheck(1)
   547  		return e
   548  	}
   549  	// fn is not a defined function. It must be ABIInternal.
   550  	// Read the address from func value, i.e. *(*uintptr)(idata(fn)).
   551  	if wantABI != obj.ABIInternal {
   552  		base.ErrorfAt(pos, 0, "internal/abi.FuncPC%s does not accept func expression, which is ABIInternal", wantABI)
   553  	}
   554  	var e Node = NewUnaryExpr(pos, OIDATA, n)
   555  	e.SetType(types.Types[types.TUINTPTR].PtrTo())
   556  	e.SetTypecheck(1)
   557  	e = NewStarExpr(pos, e)
   558  	e.SetType(types.Types[types.TUINTPTR])
   559  	e.SetTypecheck(1)
   560  	return e
   561  }
   562  
   563  // DeclareParams creates Names for all of the parameters in fn's
   564  // signature and adds them to fn.Dcl.
   565  //
   566  // If setNname is true, then it also sets types.Field.Nname for each
   567  // parameter.
   568  func (fn *Func) DeclareParams(setNname bool) {
   569  	if fn.Dcl != nil {
   570  		base.FatalfAt(fn.Pos(), "%v already has Dcl", fn)
   571  	}
   572  
   573  	declareParams := func(params []*types.Field, ctxt Class, prefix string, offset int) {
   574  		for i, param := range params {
   575  			sym := param.Sym
   576  			if sym == nil || sym.IsBlank() {
   577  				sym = fn.Sym().Pkg.LookupNum(prefix, i)
   578  			}
   579  
   580  			name := NewNameAt(param.Pos, sym, param.Type)
   581  			name.Class = ctxt
   582  			name.Curfn = fn
   583  			fn.Dcl[offset+i] = name
   584  
   585  			if setNname {
   586  				param.Nname = name
   587  			}
   588  		}
   589  	}
   590  
   591  	sig := fn.Type()
   592  	params := sig.RecvParams()
   593  	results := sig.Results()
   594  
   595  	fn.Dcl = make([]*Name, len(params)+len(results))
   596  	declareParams(params, PPARAM, "~p", 0)
   597  	declareParams(results, PPARAMOUT, "~r", len(params))
   598  }
   599  

View as plain text