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.
8 "cmd/compile/internal/base"
9 "cmd/compile/internal/types"
15 // A Func corresponds to a single function in a Go program
16 // (and vice versa: each function is denoted by exactly one *Func).
18 // There are multiple nodes that represent a Func in the IR.
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
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.
33 // A method declaration is represented like functions, except f.Sym
34 // will be the qualified method name (e.g., "T.m").
36 // A method expression (T.M) is represented as an OMETHEXPR node,
37 // in which n.Left and n.Right point to the type and method, respectively.
38 // Each distinct mention of a method expression in the source code
39 // constructs a fresh node.
41 // A method value (t.M) is represented by ODOTMETH/ODOTINTER
42 // when it is called directly and by OMETHVALUE otherwise.
43 // These are like method expressions, except that for ODOTMETH/ODOTINTER,
44 // the method name is stored in Sym instead of Right.
45 // Each OMETHVALUE ends up being implemented as a new
46 // function, a bit like a closure, with its own ODCLFUNC.
47 // The OMETHVALUE uses n.Func to record the linkage to
48 // the generated ODCLFUNC, but there is no
49 // pointer from the Func back to the OMETHVALUE.
54 Nname *Name // ONAME node
55 OClosure *ClosureExpr // OCLOSURE node
57 // Extra entry code for the function. For example, allocate and initialize
58 // memory for escaping parameters.
62 // ONAME nodes for all params/locals for this func/closure, does NOT
63 // include closurevars until transforming closures during walk.
64 // Names must be listed PPARAMs, PPARAMOUTs, then PAUTOs,
65 // with PPARAMs and PPARAMOUTs in order corresponding to the function signature.
66 // However, as anonymous or blank PPARAMs are not actually declared,
67 // they are omitted from Dcl.
68 // Anonymous and blank PPARAMOUTs are declared as ~rNN and ~bNN Names, respectively.
71 // ClosureVars lists the free variables that are used within a
72 // function literal, but formally declared in an enclosing
73 // function. The variables in this slice are the closure function's
74 // own copy of the variables, which are used within its function
75 // body. They will also each have IsClosureVar set, and will have
76 // Byval set if they're captured by value.
79 // Enclosed functions that need to be compiled.
80 // Populated during walk.
83 // Parents records the parent scope of each scope within a
84 // function. The root scope (0) has no parent, so the i'th
85 // scope's parent is stored at Parents[i-1].
88 // Marks records scope boundary changes.
91 FieldTrack map[*obj.LSym]struct{}
93 LSym *obj.LSym // Linker object in this function's native ABI (Func.ABI)
97 // Closgen tracks how many closures have been generated within
98 // this function. Used by closurename for creating unique
102 Label int32 // largest auto-generated label in this function
105 WBPos src.XPos // position of first write barrier; see SetWBPos
107 Pragma PragmaFlag // go:xxx function annotations
111 // ABI is a function's "definition" ABI. This is the ABI that
112 // this function's generated code is expecting to be called by.
114 // For most functions, this will be obj.ABIInternal. It may be
115 // a different ABI for functions defined in assembly or ABI wrappers.
117 // This is included in the export data and tracked across packages.
119 // ABIRefs is the set of ABIs by which this function is referenced.
120 // For ABIs other than this function's definition ABI, the
121 // compiler generates ABI wrapper functions. This is only tracked
125 NumDefers int32 // number of defer calls in the function
126 NumReturns int32 // number of explicit returns in the function
128 // nwbrCalls records the LSyms of functions called by this
129 // function for go:nowritebarrierrec analysis. Only filled in
130 // if nowritebarrierrecCheck != nil.
131 NWBRCalls *[]SymAndPos
133 // For wrapper functions, WrappedFunc point to the original Func.
134 // Currently only used for go/defer wrappers.
138 func NewFunc(pos src.XPos) *Func {
142 // Most functions are ABIInternal. The importer or symabis
143 // pass may override this.
144 f.ABI = obj.ABIInternal
148 func (f *Func) isStmt() {}
150 func (n *Func) copy() Node { panic(n.no("copy")) }
151 func (n *Func) doChildren(do func(Node) bool) bool { return doNodes(n.Body, do) }
152 func (n *Func) editChildren(edit func(Node) Node) { editNodes(n.Body, edit) }
153 func (n *Func) editChildrenWithHidden(edit func(Node) Node) { editNodes(n.Body, edit) }
155 func (f *Func) Type() *types.Type { return f.Nname.Type() }
156 func (f *Func) Sym() *types.Sym { return f.Nname.Sym() }
157 func (f *Func) Linksym() *obj.LSym { return f.Nname.Linksym() }
158 func (f *Func) LinksymABI(abi obj.ABI) *obj.LSym { return f.Nname.LinksymABI(abi) }
160 // An Inline holds fields used for function bodies that can be inlined.
162 Cost int32 // heuristic cost of inlining this function
164 // Copies of Func.Dcl and Func.Body for use during inlining. Copies are
165 // needed because the function's dcl/body may be changed by later compiler
166 // transformations. These fields are also populated when a function from
167 // another package is imported.
171 // CanDelayResults reports whether it's safe for the inliner to delay
172 // initializing the result parameters until immediately before the
173 // "return" statement.
177 // A Mark represents a scope boundary.
179 // Pos is the position of the token that marks the scope
183 // Scope identifies the innermost scope to the right of Pos.
187 // A ScopeID represents a lexical scope within a function.
191 funcDupok = 1 << iota // duplicate definitions ok
192 funcWrapper // hide frame from users (elide in tracebacks, don't count as a frame for recover())
193 funcABIWrapper // is an ABI wrapper (also set flagWrapper)
194 funcNeedctxt // function uses context register (has closure variables)
195 funcReflectMethod // function calls reflect.Type.Method or MethodByName
196 // true if closure inside a function; false if a simple function or a
197 // closure in a global variable initialization
199 funcIsDeadcodeClosure // true if closure is deadcode
200 funcHasDefer // contains a defer statement
201 funcNilCheckDisabled // disable nil checks when compiling this function
202 funcInlinabilityChecked // inliner has already determined whether the function is inlinable
203 funcExportInline // include inline body in export data
204 funcInstrumentBody // add race/msan/asan instrumentation during SSA construction
205 funcOpenCodedDeferDisallowed // can't do open-coded defers
206 funcClosureCalled // closure is only immediately called; used by escape analysis
209 type SymAndPos struct {
210 Sym *obj.LSym // LSym of callee
211 Pos src.XPos // line of call
214 func (f *Func) Dupok() bool { return f.flags&funcDupok != 0 }
215 func (f *Func) Wrapper() bool { return f.flags&funcWrapper != 0 }
216 func (f *Func) ABIWrapper() bool { return f.flags&funcABIWrapper != 0 }
217 func (f *Func) Needctxt() bool { return f.flags&funcNeedctxt != 0 }
218 func (f *Func) ReflectMethod() bool { return f.flags&funcReflectMethod != 0 }
219 func (f *Func) IsHiddenClosure() bool { return f.flags&funcIsHiddenClosure != 0 }
220 func (f *Func) IsDeadcodeClosure() bool { return f.flags&funcIsDeadcodeClosure != 0 }
221 func (f *Func) HasDefer() bool { return f.flags&funcHasDefer != 0 }
222 func (f *Func) NilCheckDisabled() bool { return f.flags&funcNilCheckDisabled != 0 }
223 func (f *Func) InlinabilityChecked() bool { return f.flags&funcInlinabilityChecked != 0 }
224 func (f *Func) ExportInline() bool { return f.flags&funcExportInline != 0 }
225 func (f *Func) InstrumentBody() bool { return f.flags&funcInstrumentBody != 0 }
226 func (f *Func) OpenCodedDeferDisallowed() bool { return f.flags&funcOpenCodedDeferDisallowed != 0 }
227 func (f *Func) ClosureCalled() bool { return f.flags&funcClosureCalled != 0 }
229 func (f *Func) SetDupok(b bool) { f.flags.set(funcDupok, b) }
230 func (f *Func) SetWrapper(b bool) { f.flags.set(funcWrapper, b) }
231 func (f *Func) SetABIWrapper(b bool) { f.flags.set(funcABIWrapper, b) }
232 func (f *Func) SetNeedctxt(b bool) { f.flags.set(funcNeedctxt, b) }
233 func (f *Func) SetReflectMethod(b bool) { f.flags.set(funcReflectMethod, b) }
234 func (f *Func) SetIsHiddenClosure(b bool) { f.flags.set(funcIsHiddenClosure, b) }
235 func (f *Func) SetIsDeadcodeClosure(b bool) { f.flags.set(funcIsDeadcodeClosure, b) }
236 func (f *Func) SetHasDefer(b bool) { f.flags.set(funcHasDefer, b) }
237 func (f *Func) SetNilCheckDisabled(b bool) { f.flags.set(funcNilCheckDisabled, b) }
238 func (f *Func) SetInlinabilityChecked(b bool) { f.flags.set(funcInlinabilityChecked, b) }
239 func (f *Func) SetExportInline(b bool) { f.flags.set(funcExportInline, b) }
240 func (f *Func) SetInstrumentBody(b bool) { f.flags.set(funcInstrumentBody, b) }
241 func (f *Func) SetOpenCodedDeferDisallowed(b bool) { f.flags.set(funcOpenCodedDeferDisallowed, b) }
242 func (f *Func) SetClosureCalled(b bool) { f.flags.set(funcClosureCalled, b) }
244 func (f *Func) SetWBPos(pos src.XPos) {
245 if base.Debug.WB != 0 {
246 base.WarnfAt(pos, "write barrier")
248 if !f.WBPos.IsKnown() {
253 // FuncName returns the name (without the package) of the function n.
254 func FuncName(f *Func) string {
255 if f == nil || f.Nname == nil {
261 // PkgFuncName returns the name of the function referenced by n, with package prepended.
262 // This differs from the compiler's internal convention where local functions lack a package
263 // because the ultimate consumer of this is a human looking at an IDE; package is only empty
264 // if the compilation package is actually the empty string.
265 func PkgFuncName(f *Func) string {
266 if f == nil || f.Nname == nil {
272 return pkg.Path + "." + s.Name
277 // WithFunc invokes do with CurFunc and base.Pos set to curfn and
278 // curfn.Pos(), respectively, and then restores their previous values
280 func WithFunc(curfn *Func, do func()) {
281 oldfn, oldpos := CurFunc, base.Pos
282 defer func() { CurFunc, base.Pos = oldfn, oldpos }()
284 CurFunc, base.Pos = curfn, curfn.Pos()
288 func FuncSymName(s *types.Sym) string {
292 // MarkFunc marks a node as a function.
293 func MarkFunc(n *Name) {
294 if n.Op() != ONAME || n.Class != Pxxx {
295 base.FatalfAt(n.Pos(), "expected ONAME/Pxxx node, got %v (%v/%v)", n, n.Op(), n.Class)
299 n.Sym().SetFunc(true)
302 // ClosureDebugRuntimeCheck applies boilerplate checks for debug flags
303 // and compiling runtime.
304 func ClosureDebugRuntimeCheck(clo *ClosureExpr) {
305 if base.Debug.Closure > 0 {
306 if clo.Esc() == EscHeap {
307 base.WarnfAt(clo.Pos(), "heap closure, captured vars = %v", clo.Func.ClosureVars)
309 base.WarnfAt(clo.Pos(), "stack closure, captured vars = %v", clo.Func.ClosureVars)
312 if base.Flag.CompilingRuntime && clo.Esc() == EscHeap && !clo.IsGoWrap {
313 base.ErrorfAt(clo.Pos(), "heap-allocated closure %s, not allowed in runtime", FuncName(clo.Func))
317 // IsTrivialClosure reports whether closure clo has an
318 // empty list of captured vars.
319 func IsTrivialClosure(clo *ClosureExpr) bool {
320 return len(clo.Func.ClosureVars) == 0
323 // globClosgen is like Func.Closgen, but for the global scope.
324 var globClosgen int32
326 // closureName generates a new unique name for a closure within outerfn.
327 func closureName(outerfn *Func) *types.Sym {
328 pkg := types.LocalPkg
334 if outerfn.OClosure != nil {
338 pkg = outerfn.Sym().Pkg
339 outer = FuncName(outerfn)
341 // There may be multiple functions named "_". In those
342 // cases, we can't use their individual Closgens as it
343 // would lead to name clashes.
344 if !IsBlank(outerfn.Nname) {
345 gen = &outerfn.Closgen
350 return pkg.Lookup(fmt.Sprintf("%s.%s%d", outer, prefix, *gen))
353 // NewClosureFunc creates a new Func to represent a function literal.
354 // If hidden is true, then the closure is marked hidden (i.e., as a
355 // function literal contained within another function, rather than a
356 // package-scope variable initialization expression).
357 func NewClosureFunc(pos src.XPos, hidden bool) *Func {
359 fn.SetIsHiddenClosure(hidden)
361 fn.Nname = NewNameAt(pos, BlankNode.Sym())
365 fn.OClosure = &ClosureExpr{Func: fn}
366 fn.OClosure.op = OCLOSURE
367 fn.OClosure.pos = pos
372 // NameClosure generates a unique for the given function literal,
373 // which must have appeared within outerfn.
374 func NameClosure(clo *ClosureExpr, outerfn *Func) {
376 if fn.IsHiddenClosure() != (outerfn != nil) {
377 base.FatalfAt(clo.Pos(), "closure naming inconsistency: hidden %v, but outer %v", fn.IsHiddenClosure(), outerfn)
382 base.FatalfAt(clo.Pos(), "closure already named: %v", name)
385 name.SetSym(closureName(outerfn))
389 // UseClosure checks that the given function literal has been setup
390 // correctly, and then returns it as an expression.
391 // It must be called after clo.Func.ClosureVars has been set.
392 func UseClosure(clo *ClosureExpr, pkg *Package) Node {
397 base.FatalfAt(fn.Pos(), "unnamed closure func: %v", fn)
399 // Caution: clo.Typecheck() is still 0 when UseClosure is called by
401 if fn.Typecheck() != 1 || name.Typecheck() != 1 {
402 base.FatalfAt(fn.Pos(), "missed typecheck: %v", fn)
404 if clo.Type() == nil || name.Type() == nil {
405 base.FatalfAt(fn.Pos(), "missing types: %v", fn)
407 if !types.Identical(clo.Type(), name.Type()) {
408 base.FatalfAt(fn.Pos(), "mismatched types: %v", fn)
412 s := fmt.Sprintf("new closure func: %v", fn)
417 pkg.Decls = append(pkg.Decls, fn)
420 if false && IsTrivialClosure(clo) {
421 // TODO(mdempsky): Investigate if we can/should optimize this
422 // case. walkClosure already handles it later, but it could be
423 // useful to recognize earlier (e.g., it might allow multiple
424 // inlined calls to a function to share a common trivial closure
425 // func, rather than cloning it for each inlined call).