mirror of
https://github.com/golang/go
synced 2024-11-24 01:30:10 -07:00
[dev.regabi] cmd/compile: move func code from node.go to func.go
No code changes here, only copying of text. This will make the diffs in a future CL readable. Passes buildall w/ toolstash -cmp. Change-Id: I325a62e79edd82f1437769891ea63a32f51c0170 Reviewed-on: https://go-review.googlesource.com/c/go/+/274095 Trust: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
862f638a89
commit
65ae15ac5d
216
src/cmd/compile/internal/ir/func.go
Normal file
216
src/cmd/compile/internal/ir/func.go
Normal file
@ -0,0 +1,216 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ir
|
||||
|
||||
import (
|
||||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/src"
|
||||
)
|
||||
|
||||
// A Func corresponds to a single function in a Go program
|
||||
// (and vice versa: each function is denoted by exactly one *Func).
|
||||
//
|
||||
// There are multiple nodes that represent a Func in the IR.
|
||||
//
|
||||
// The ONAME node (Func.Name) is used for plain references to it.
|
||||
// The ODCLFUNC node (Func.Decl) is used for its declaration code.
|
||||
// The OCLOSURE node (Func.Closure) is used for a reference to a
|
||||
// function literal.
|
||||
//
|
||||
// A Func for an imported function will have only an ONAME node.
|
||||
// A declared function or method has an ONAME and an ODCLFUNC.
|
||||
// A function literal is represented directly by an OCLOSURE, but it also
|
||||
// has an ODCLFUNC (and a matching ONAME) representing the compiled
|
||||
// underlying form of the closure, which accesses the captured variables
|
||||
// using a special data structure passed in a register.
|
||||
//
|
||||
// A method declaration is represented like functions, except f.Sym
|
||||
// will be the qualified method name (e.g., "T.m") and
|
||||
// f.Func.Shortname is the bare method name (e.g., "m").
|
||||
//
|
||||
// A method expression (T.M) is represented as an OMETHEXPR node,
|
||||
// in which n.Left and n.Right point to the type and method, respectively.
|
||||
// Each distinct mention of a method expression in the source code
|
||||
// constructs a fresh node.
|
||||
//
|
||||
// A method value (t.M) is represented by ODOTMETH/ODOTINTER
|
||||
// when it is called directly and by OCALLPART otherwise.
|
||||
// These are like method expressions, except that for ODOTMETH/ODOTINTER,
|
||||
// the method name is stored in Sym instead of Right.
|
||||
// Each OCALLPART ends up being implemented as a new
|
||||
// function, a bit like a closure, with its own ODCLFUNC.
|
||||
// The OCALLPART has uses n.Func to record the linkage to
|
||||
// the generated ODCLFUNC (as n.Func.Decl), but there is no
|
||||
// pointer from the Func back to the OCALLPART.
|
||||
type Func struct {
|
||||
Nname Node // ONAME node
|
||||
Decl Node // ODCLFUNC node
|
||||
OClosure Node // OCLOSURE node
|
||||
|
||||
Shortname *types.Sym
|
||||
|
||||
// Extra entry code for the function. For example, allocate and initialize
|
||||
// memory for escaping parameters.
|
||||
Enter Nodes
|
||||
Exit Nodes
|
||||
// ONAME nodes for all params/locals for this func/closure, does NOT
|
||||
// include closurevars until transformclosure runs.
|
||||
Dcl []Node
|
||||
|
||||
ClosureEnter Nodes // list of ONAME nodes of captured variables
|
||||
ClosureType Node // closure representation type
|
||||
ClosureCalled bool // closure is only immediately called
|
||||
ClosureVars Nodes // closure params; each has closurevar set
|
||||
|
||||
// Parents records the parent scope of each scope within a
|
||||
// function. The root scope (0) has no parent, so the i'th
|
||||
// scope's parent is stored at Parents[i-1].
|
||||
Parents []ScopeID
|
||||
|
||||
// Marks records scope boundary changes.
|
||||
Marks []Mark
|
||||
|
||||
// Closgen tracks how many closures have been generated within
|
||||
// this function. Used by closurename for creating unique
|
||||
// function names.
|
||||
Closgen int
|
||||
|
||||
FieldTrack map[*types.Sym]struct{}
|
||||
DebugInfo interface{}
|
||||
LSym *obj.LSym
|
||||
|
||||
Inl *Inline
|
||||
|
||||
Label int32 // largest auto-generated label in this function
|
||||
|
||||
Endlineno src.XPos
|
||||
WBPos src.XPos // position of first write barrier; see SetWBPos
|
||||
|
||||
Pragma PragmaFlag // go:xxx function annotations
|
||||
|
||||
flags bitset16
|
||||
NumDefers int // number of defer calls in the function
|
||||
NumReturns int // number of explicit returns in the function
|
||||
|
||||
// nwbrCalls records the LSyms of functions called by this
|
||||
// function for go:nowritebarrierrec analysis. Only filled in
|
||||
// if nowritebarrierrecCheck != nil.
|
||||
NWBRCalls *[]SymAndPos
|
||||
}
|
||||
|
||||
// An Inline holds fields used for function bodies that can be inlined.
|
||||
type Inline struct {
|
||||
Cost int32 // heuristic cost of inlining this function
|
||||
|
||||
// Copies of Func.Dcl and Nbody for use during inlining.
|
||||
Dcl []Node
|
||||
Body []Node
|
||||
}
|
||||
|
||||
// A Mark represents a scope boundary.
|
||||
type Mark struct {
|
||||
// Pos is the position of the token that marks the scope
|
||||
// change.
|
||||
Pos src.XPos
|
||||
|
||||
// Scope identifies the innermost scope to the right of Pos.
|
||||
Scope ScopeID
|
||||
}
|
||||
|
||||
// A ScopeID represents a lexical scope within a function.
|
||||
type ScopeID int32
|
||||
|
||||
const (
|
||||
funcDupok = 1 << iota // duplicate definitions ok
|
||||
funcWrapper // is method wrapper
|
||||
funcNeedctxt // function uses context register (has closure variables)
|
||||
funcReflectMethod // function calls reflect.Type.Method or MethodByName
|
||||
// true if closure inside a function; false if a simple function or a
|
||||
// closure in a global variable initialization
|
||||
funcIsHiddenClosure
|
||||
funcHasDefer // contains a defer statement
|
||||
funcNilCheckDisabled // disable nil checks when compiling this function
|
||||
funcInlinabilityChecked // inliner has already determined whether the function is inlinable
|
||||
funcExportInline // include inline body in export data
|
||||
funcInstrumentBody // add race/msan instrumentation during SSA construction
|
||||
funcOpenCodedDeferDisallowed // can't do open-coded defers
|
||||
)
|
||||
|
||||
type SymAndPos struct {
|
||||
Sym *obj.LSym // LSym of callee
|
||||
Pos src.XPos // line of call
|
||||
}
|
||||
|
||||
func (f *Func) Dupok() bool { return f.flags&funcDupok != 0 }
|
||||
func (f *Func) Wrapper() bool { return f.flags&funcWrapper != 0 }
|
||||
func (f *Func) Needctxt() bool { return f.flags&funcNeedctxt != 0 }
|
||||
func (f *Func) ReflectMethod() bool { return f.flags&funcReflectMethod != 0 }
|
||||
func (f *Func) IsHiddenClosure() bool { return f.flags&funcIsHiddenClosure != 0 }
|
||||
func (f *Func) HasDefer() bool { return f.flags&funcHasDefer != 0 }
|
||||
func (f *Func) NilCheckDisabled() bool { return f.flags&funcNilCheckDisabled != 0 }
|
||||
func (f *Func) InlinabilityChecked() bool { return f.flags&funcInlinabilityChecked != 0 }
|
||||
func (f *Func) ExportInline() bool { return f.flags&funcExportInline != 0 }
|
||||
func (f *Func) InstrumentBody() bool { return f.flags&funcInstrumentBody != 0 }
|
||||
func (f *Func) OpenCodedDeferDisallowed() bool { return f.flags&funcOpenCodedDeferDisallowed != 0 }
|
||||
|
||||
func (f *Func) SetDupok(b bool) { f.flags.set(funcDupok, b) }
|
||||
func (f *Func) SetWrapper(b bool) { f.flags.set(funcWrapper, b) }
|
||||
func (f *Func) SetNeedctxt(b bool) { f.flags.set(funcNeedctxt, b) }
|
||||
func (f *Func) SetReflectMethod(b bool) { f.flags.set(funcReflectMethod, b) }
|
||||
func (f *Func) SetIsHiddenClosure(b bool) { f.flags.set(funcIsHiddenClosure, b) }
|
||||
func (f *Func) SetHasDefer(b bool) { f.flags.set(funcHasDefer, b) }
|
||||
func (f *Func) SetNilCheckDisabled(b bool) { f.flags.set(funcNilCheckDisabled, b) }
|
||||
func (f *Func) SetInlinabilityChecked(b bool) { f.flags.set(funcInlinabilityChecked, b) }
|
||||
func (f *Func) SetExportInline(b bool) { f.flags.set(funcExportInline, b) }
|
||||
func (f *Func) SetInstrumentBody(b bool) { f.flags.set(funcInstrumentBody, b) }
|
||||
func (f *Func) SetOpenCodedDeferDisallowed(b bool) { f.flags.set(funcOpenCodedDeferDisallowed, b) }
|
||||
|
||||
func (f *Func) SetWBPos(pos src.XPos) {
|
||||
if base.Debug.WB != 0 {
|
||||
base.WarnfAt(pos, "write barrier")
|
||||
}
|
||||
if !f.WBPos.IsKnown() {
|
||||
f.WBPos = pos
|
||||
}
|
||||
}
|
||||
|
||||
// funcname returns the name (without the package) of the function n.
|
||||
func FuncName(n Node) string {
|
||||
if n == nil || n.Func() == nil || n.Func().Nname == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
return n.Func().Nname.Sym().Name
|
||||
}
|
||||
|
||||
// pkgFuncName returns the name of the function referenced by n, with package prepended.
|
||||
// This differs from the compiler's internal convention where local functions lack a package
|
||||
// because the ultimate consumer of this is a human looking at an IDE; package is only empty
|
||||
// if the compilation package is actually the empty string.
|
||||
func PkgFuncName(n Node) string {
|
||||
var s *types.Sym
|
||||
if n == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
if n.Op() == ONAME {
|
||||
s = n.Sym()
|
||||
} else {
|
||||
if n.Func() == nil || n.Func().Nname == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
s = n.Func().Nname.Sym()
|
||||
}
|
||||
pkg := s.Pkg
|
||||
|
||||
p := base.Ctxt.Pkgpath
|
||||
if pkg != nil && pkg.Path != "" {
|
||||
p = pkg.Path
|
||||
}
|
||||
if p == "" {
|
||||
return s.Name
|
||||
}
|
||||
return p + "." + s.Name
|
||||
}
|
@ -14,7 +14,6 @@ import (
|
||||
|
||||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/src"
|
||||
)
|
||||
|
||||
@ -403,209 +402,10 @@ func MayBeShared(n Node) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// funcname returns the name (without the package) of the function n.
|
||||
func FuncName(n Node) string {
|
||||
if n == nil || n.Func() == nil || n.Func().Nname == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
return n.Func().Nname.Sym().Name
|
||||
}
|
||||
|
||||
// pkgFuncName returns the name of the function referenced by n, with package prepended.
|
||||
// This differs from the compiler's internal convention where local functions lack a package
|
||||
// because the ultimate consumer of this is a human looking at an IDE; package is only empty
|
||||
// if the compilation package is actually the empty string.
|
||||
func PkgFuncName(n Node) string {
|
||||
var s *types.Sym
|
||||
if n == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
if n.Op() == ONAME {
|
||||
s = n.Sym()
|
||||
} else {
|
||||
if n.Func() == nil || n.Func().Nname == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
s = n.Func().Nname.Sym()
|
||||
}
|
||||
pkg := s.Pkg
|
||||
|
||||
p := base.Ctxt.Pkgpath
|
||||
if pkg != nil && pkg.Path != "" {
|
||||
p = pkg.Path
|
||||
}
|
||||
if p == "" {
|
||||
return s.Name
|
||||
}
|
||||
return p + "." + s.Name
|
||||
}
|
||||
|
||||
// The compiler needs *Node to be assignable to cmd/compile/internal/ssa.Sym.
|
||||
func (n *node) CanBeAnSSASym() {
|
||||
}
|
||||
|
||||
// A Func corresponds to a single function in a Go program
|
||||
// (and vice versa: each function is denoted by exactly one *Func).
|
||||
//
|
||||
// There are multiple nodes that represent a Func in the IR.
|
||||
//
|
||||
// The ONAME node (Func.Name) is used for plain references to it.
|
||||
// The ODCLFUNC node (Func.Decl) is used for its declaration code.
|
||||
// The OCLOSURE node (Func.Closure) is used for a reference to a
|
||||
// function literal.
|
||||
//
|
||||
// A Func for an imported function will have only an ONAME node.
|
||||
// A declared function or method has an ONAME and an ODCLFUNC.
|
||||
// A function literal is represented directly by an OCLOSURE, but it also
|
||||
// has an ODCLFUNC (and a matching ONAME) representing the compiled
|
||||
// underlying form of the closure, which accesses the captured variables
|
||||
// using a special data structure passed in a register.
|
||||
//
|
||||
// A method declaration is represented like functions, except f.Sym
|
||||
// will be the qualified method name (e.g., "T.m") and
|
||||
// f.Func.Shortname is the bare method name (e.g., "m").
|
||||
//
|
||||
// A method expression (T.M) is represented as an OMETHEXPR node,
|
||||
// in which n.Left and n.Right point to the type and method, respectively.
|
||||
// Each distinct mention of a method expression in the source code
|
||||
// constructs a fresh node.
|
||||
//
|
||||
// A method value (t.M) is represented by ODOTMETH/ODOTINTER
|
||||
// when it is called directly and by OCALLPART otherwise.
|
||||
// These are like method expressions, except that for ODOTMETH/ODOTINTER,
|
||||
// the method name is stored in Sym instead of Right.
|
||||
// Each OCALLPART ends up being implemented as a new
|
||||
// function, a bit like a closure, with its own ODCLFUNC.
|
||||
// The OCALLPART has uses n.Func to record the linkage to
|
||||
// the generated ODCLFUNC (as n.Func.Decl), but there is no
|
||||
// pointer from the Func back to the OCALLPART.
|
||||
type Func struct {
|
||||
Nname Node // ONAME node
|
||||
Decl Node // ODCLFUNC node
|
||||
OClosure Node // OCLOSURE node
|
||||
|
||||
Shortname *types.Sym
|
||||
|
||||
// Extra entry code for the function. For example, allocate and initialize
|
||||
// memory for escaping parameters.
|
||||
Enter Nodes
|
||||
Exit Nodes
|
||||
// ONAME nodes for all params/locals for this func/closure, does NOT
|
||||
// include closurevars until transformclosure runs.
|
||||
Dcl []Node
|
||||
|
||||
ClosureEnter Nodes // list of ONAME nodes of captured variables
|
||||
ClosureType Node // closure representation type
|
||||
ClosureCalled bool // closure is only immediately called
|
||||
ClosureVars Nodes // closure params; each has closurevar set
|
||||
|
||||
// Parents records the parent scope of each scope within a
|
||||
// function. The root scope (0) has no parent, so the i'th
|
||||
// scope's parent is stored at Parents[i-1].
|
||||
Parents []ScopeID
|
||||
|
||||
// Marks records scope boundary changes.
|
||||
Marks []Mark
|
||||
|
||||
// Closgen tracks how many closures have been generated within
|
||||
// this function. Used by closurename for creating unique
|
||||
// function names.
|
||||
Closgen int
|
||||
|
||||
FieldTrack map[*types.Sym]struct{}
|
||||
DebugInfo interface{}
|
||||
LSym *obj.LSym
|
||||
|
||||
Inl *Inline
|
||||
|
||||
Label int32 // largest auto-generated label in this function
|
||||
|
||||
Endlineno src.XPos
|
||||
WBPos src.XPos // position of first write barrier; see SetWBPos
|
||||
|
||||
Pragma PragmaFlag // go:xxx function annotations
|
||||
|
||||
flags bitset16
|
||||
NumDefers int // number of defer calls in the function
|
||||
NumReturns int // number of explicit returns in the function
|
||||
|
||||
// nwbrCalls records the LSyms of functions called by this
|
||||
// function for go:nowritebarrierrec analysis. Only filled in
|
||||
// if nowritebarrierrecCheck != nil.
|
||||
NWBRCalls *[]SymAndPos
|
||||
}
|
||||
|
||||
// An Inline holds fields used for function bodies that can be inlined.
|
||||
type Inline struct {
|
||||
Cost int32 // heuristic cost of inlining this function
|
||||
|
||||
// Copies of Func.Dcl and Nbody for use during inlining.
|
||||
Dcl []Node
|
||||
Body []Node
|
||||
}
|
||||
|
||||
// A Mark represents a scope boundary.
|
||||
type Mark struct {
|
||||
// Pos is the position of the token that marks the scope
|
||||
// change.
|
||||
Pos src.XPos
|
||||
|
||||
// Scope identifies the innermost scope to the right of Pos.
|
||||
Scope ScopeID
|
||||
}
|
||||
|
||||
// A ScopeID represents a lexical scope within a function.
|
||||
type ScopeID int32
|
||||
|
||||
const (
|
||||
funcDupok = 1 << iota // duplicate definitions ok
|
||||
funcWrapper // is method wrapper
|
||||
funcNeedctxt // function uses context register (has closure variables)
|
||||
funcReflectMethod // function calls reflect.Type.Method or MethodByName
|
||||
// true if closure inside a function; false if a simple function or a
|
||||
// closure in a global variable initialization
|
||||
funcIsHiddenClosure
|
||||
funcHasDefer // contains a defer statement
|
||||
funcNilCheckDisabled // disable nil checks when compiling this function
|
||||
funcInlinabilityChecked // inliner has already determined whether the function is inlinable
|
||||
funcExportInline // include inline body in export data
|
||||
funcInstrumentBody // add race/msan instrumentation during SSA construction
|
||||
funcOpenCodedDeferDisallowed // can't do open-coded defers
|
||||
)
|
||||
|
||||
func (f *Func) Dupok() bool { return f.flags&funcDupok != 0 }
|
||||
func (f *Func) Wrapper() bool { return f.flags&funcWrapper != 0 }
|
||||
func (f *Func) Needctxt() bool { return f.flags&funcNeedctxt != 0 }
|
||||
func (f *Func) ReflectMethod() bool { return f.flags&funcReflectMethod != 0 }
|
||||
func (f *Func) IsHiddenClosure() bool { return f.flags&funcIsHiddenClosure != 0 }
|
||||
func (f *Func) HasDefer() bool { return f.flags&funcHasDefer != 0 }
|
||||
func (f *Func) NilCheckDisabled() bool { return f.flags&funcNilCheckDisabled != 0 }
|
||||
func (f *Func) InlinabilityChecked() bool { return f.flags&funcInlinabilityChecked != 0 }
|
||||
func (f *Func) ExportInline() bool { return f.flags&funcExportInline != 0 }
|
||||
func (f *Func) InstrumentBody() bool { return f.flags&funcInstrumentBody != 0 }
|
||||
func (f *Func) OpenCodedDeferDisallowed() bool { return f.flags&funcOpenCodedDeferDisallowed != 0 }
|
||||
|
||||
func (f *Func) SetDupok(b bool) { f.flags.set(funcDupok, b) }
|
||||
func (f *Func) SetWrapper(b bool) { f.flags.set(funcWrapper, b) }
|
||||
func (f *Func) SetNeedctxt(b bool) { f.flags.set(funcNeedctxt, b) }
|
||||
func (f *Func) SetReflectMethod(b bool) { f.flags.set(funcReflectMethod, b) }
|
||||
func (f *Func) SetIsHiddenClosure(b bool) { f.flags.set(funcIsHiddenClosure, b) }
|
||||
func (f *Func) SetHasDefer(b bool) { f.flags.set(funcHasDefer, b) }
|
||||
func (f *Func) SetNilCheckDisabled(b bool) { f.flags.set(funcNilCheckDisabled, b) }
|
||||
func (f *Func) SetInlinabilityChecked(b bool) { f.flags.set(funcInlinabilityChecked, b) }
|
||||
func (f *Func) SetExportInline(b bool) { f.flags.set(funcExportInline, b) }
|
||||
func (f *Func) SetInstrumentBody(b bool) { f.flags.set(funcInstrumentBody, b) }
|
||||
func (f *Func) SetOpenCodedDeferDisallowed(b bool) { f.flags.set(funcOpenCodedDeferDisallowed, b) }
|
||||
|
||||
func (f *Func) SetWBPos(pos src.XPos) {
|
||||
if base.Debug.WB != 0 {
|
||||
base.WarnfAt(pos, "write barrier")
|
||||
}
|
||||
if !f.WBPos.IsKnown() {
|
||||
f.WBPos = pos
|
||||
}
|
||||
}
|
||||
|
||||
//go:generate stringer -type=Op -trimprefix=O
|
||||
|
||||
type Op uint8
|
||||
@ -1111,11 +911,6 @@ const (
|
||||
GoBuildPragma
|
||||
)
|
||||
|
||||
type SymAndPos struct {
|
||||
Sym *obj.LSym // LSym of callee
|
||||
Pos src.XPos // line of call
|
||||
}
|
||||
|
||||
func AsNode(n types.IRNode) Node {
|
||||
if n == nil {
|
||||
return nil
|
||||
|
Loading…
Reference in New Issue
Block a user