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