]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/ir/func.go
all: fix typos in go file comments
[gostls13.git] / 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").
35 //
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.
40 //
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.
50 type Func struct {
51         miniNode
52         Body Nodes
53
54         Nname    *Name        // ONAME node
55         OClosure *ClosureExpr // OCLOSURE node
56
57         // Extra entry code for the function. For example, allocate and initialize
58         // memory for escaping parameters.
59         Enter Nodes
60         Exit  Nodes
61
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.
69         Dcl []*Name
70
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.
77         ClosureVars []*Name
78
79         // Enclosed functions that need to be compiled.
80         // Populated during walk.
81         Closures []*Func
82
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].
86         Parents []ScopeID
87
88         // Marks records scope boundary changes.
89         Marks []Mark
90
91         FieldTrack map[*obj.LSym]struct{}
92         DebugInfo  interface{}
93         LSym       *obj.LSym // Linker object in this function's native ABI (Func.ABI)
94
95         Inl *Inline
96
97         // Closgen tracks how many closures have been generated within
98         // this function. Used by closurename for creating unique
99         // function names.
100         Closgen int32
101
102         Label int32 // largest auto-generated label in this function
103
104         Endlineno src.XPos
105         WBPos     src.XPos // position of first write barrier; see SetWBPos
106
107         Pragma PragmaFlag // go:xxx function annotations
108
109         flags bitset16
110
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.
113         //
114         // For most functions, this will be obj.ABIInternal. It may be
115         // a different ABI for functions defined in assembly or ABI wrappers.
116         //
117         // This is included in the export data and tracked across packages.
118         ABI obj.ABI
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
122         // within a package.
123         ABIRefs obj.ABISet
124
125         NumDefers  int32 // number of defer calls in the function
126         NumReturns int32 // number of explicit returns in the function
127
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
132
133         // For wrapper functions, WrappedFunc point to the original Func.
134         // Currently only used for go/defer wrappers.
135         WrappedFunc *Func
136 }
137
138 func NewFunc(pos src.XPos) *Func {
139         f := new(Func)
140         f.pos = pos
141         f.op = ODCLFUNC
142         // Most functions are ABIInternal. The importer or symabis
143         // pass may override this.
144         f.ABI = obj.ABIInternal
145         return f
146 }
147
148 func (f *Func) isStmt() {}
149
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) }
154
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) }
159
160 // An Inline holds fields used for function bodies that can be inlined.
161 type Inline struct {
162         Cost int32 // heuristic cost of inlining this function
163
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.
168         Dcl  []*Name
169         Body []Node
170
171         // CanDelayResults reports whether it's safe for the inliner to delay
172         // initializing the result parameters until immediately before the
173         // "return" statement.
174         CanDelayResults bool
175 }
176
177 // A Mark represents a scope boundary.
178 type Mark struct {
179         // Pos is the position of the token that marks the scope
180         // change.
181         Pos src.XPos
182
183         // Scope identifies the innermost scope to the right of Pos.
184         Scope ScopeID
185 }
186
187 // A ScopeID represents a lexical scope within a function.
188 type ScopeID int32
189
190 const (
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
198         funcIsHiddenClosure
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
207 )
208
209 type SymAndPos struct {
210         Sym *obj.LSym // LSym of callee
211         Pos src.XPos  // line of call
212 }
213
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 }
228
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) }
243
244 func (f *Func) SetWBPos(pos src.XPos) {
245         if base.Debug.WB != 0 {
246                 base.WarnfAt(pos, "write barrier")
247         }
248         if !f.WBPos.IsKnown() {
249                 f.WBPos = pos
250         }
251 }
252
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 {
256                 return "<nil>"
257         }
258         return f.Sym().Name
259 }
260
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 {
267                 return "<nil>"
268         }
269         s := f.Sym()
270         pkg := s.Pkg
271
272         return pkg.Path + "." + s.Name
273 }
274
275 var CurFunc *Func
276
277 // WithFunc invokes do with CurFunc and base.Pos set to curfn and
278 // curfn.Pos(), respectively, and then restores their previous values
279 // before returning.
280 func WithFunc(curfn *Func, do func()) {
281         oldfn, oldpos := CurFunc, base.Pos
282         defer func() { CurFunc, base.Pos = oldfn, oldpos }()
283
284         CurFunc, base.Pos = curfn, curfn.Pos()
285         do()
286 }
287
288 func FuncSymName(s *types.Sym) string {
289         return s.Name + "·f"
290 }
291
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)
296         }
297
298         n.Class = PFUNC
299         n.Sym().SetFunc(true)
300 }
301
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)
308                 } else {
309                         base.WarnfAt(clo.Pos(), "stack closure, captured vars = %v", clo.Func.ClosureVars)
310                 }
311         }
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))
314         }
315 }
316
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
321 }
322
323 // globClosgen is like Func.Closgen, but for the global scope.
324 var globClosgen int32
325
326 // closureName generates a new unique name for a closure within outerfn.
327 func closureName(outerfn *Func) *types.Sym {
328         pkg := types.LocalPkg
329         outer := "glob."
330         prefix := "func"
331         gen := &globClosgen
332
333         if outerfn != nil {
334                 if outerfn.OClosure != nil {
335                         prefix = ""
336                 }
337
338                 pkg = outerfn.Sym().Pkg
339                 outer = FuncName(outerfn)
340
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
346                 }
347         }
348
349         *gen++
350         return pkg.Lookup(fmt.Sprintf("%s.%s%d", outer, prefix, *gen))
351 }
352
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 {
358         fn := NewFunc(pos)
359         fn.SetIsHiddenClosure(hidden)
360
361         fn.Nname = NewNameAt(pos, BlankNode.Sym())
362         fn.Nname.Func = fn
363         fn.Nname.Defn = fn
364
365         fn.OClosure = &ClosureExpr{Func: fn}
366         fn.OClosure.op = OCLOSURE
367         fn.OClosure.pos = pos
368
369         return fn
370 }
371
372 // NameClosure generates a unique for the given function literal,
373 // which must have appeared within outerfn.
374 func NameClosure(clo *ClosureExpr, outerfn *Func) {
375         fn := clo.Func
376         if fn.IsHiddenClosure() != (outerfn != nil) {
377                 base.FatalfAt(clo.Pos(), "closure naming inconsistency: hidden %v, but outer %v", fn.IsHiddenClosure(), outerfn)
378         }
379
380         name := fn.Nname
381         if !IsBlank(name) {
382                 base.FatalfAt(clo.Pos(), "closure already named: %v", name)
383         }
384
385         name.SetSym(closureName(outerfn))
386         MarkFunc(name)
387 }
388
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 {
393         fn := clo.Func
394         name := fn.Nname
395
396         if IsBlank(name) {
397                 base.FatalfAt(fn.Pos(), "unnamed closure func: %v", fn)
398         }
399         // Caution: clo.Typecheck() is still 0 when UseClosure is called by
400         // tcClosure.
401         if fn.Typecheck() != 1 || name.Typecheck() != 1 {
402                 base.FatalfAt(fn.Pos(), "missed typecheck: %v", fn)
403         }
404         if clo.Type() == nil || name.Type() == nil {
405                 base.FatalfAt(fn.Pos(), "missing types: %v", fn)
406         }
407         if !types.Identical(clo.Type(), name.Type()) {
408                 base.FatalfAt(fn.Pos(), "mismatched types: %v", fn)
409         }
410
411         if base.Flag.W > 1 {
412                 s := fmt.Sprintf("new closure func: %v", fn)
413                 Dump(s, fn)
414         }
415
416         if pkg != nil {
417                 pkg.Decls = append(pkg.Decls, fn)
418         }
419
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).
426         }
427
428         return clo
429 }