1
0
mirror of https://github.com/golang/go synced 2024-09-28 20:24:29 -06:00

cmd/compile: cleanup Func construction

This CL moves more common Func-setup logic into ir.NewFunc. In
particular, it now handles constructing the Name and wiring them
together, setting the Typecheck bit, and setting Sym.Func.

Relatedly, this CL also extends typecheck.DeclFunc to append the
function to typecheck.Target.Funcs, so that callers no longer need to
do this.

Change-Id: Ifa0aded8df0517188eb295d0dccc107af85f1e8a
Reviewed-on: https://go-review.googlesource.com/c/go/+/520338
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Matthew Dempsky 2023-08-16 19:45:12 -07:00 committed by Gopher Robot
parent 5c6fbd2c3e
commit 4e411e7bc4
12 changed files with 79 additions and 131 deletions

View File

@ -818,9 +818,8 @@ func inlcopy(n ir.Node) ir.Node {
// x.Func.Nname.Ntype, x.Func.Dcl, x.Func.ClosureVars, and
// x.Func.Body for iexport and local inlining.
oldfn := x.Func
newfn := ir.NewFunc(oldfn.Pos())
newfn := ir.NewFunc(oldfn.Pos(), oldfn.Nname.Pos(), oldfn.Nname.Sym(), oldfn.Nname.Type())
m.(*ir.ClosureExpr).Func = newfn
newfn.Nname = ir.NewNameAt(oldfn.Nname.Pos(), oldfn.Nname.Sym(), oldfn.Nname.Type())
// XXX OK to share fn.Type() ??
newfn.Body = inlcopylist(oldfn.Body)
// Make shallow copy of the Dcl and ClosureVar slices

View File

@ -147,14 +147,29 @@ type WasmImport struct {
Name string
}
func NewFunc(pos src.XPos) *Func {
f := new(Func)
f.pos = pos
f.op = ODCLFUNC
// NewFunc returns a new Func with the given name and type.
//
// fpos is the position of the "func" token, and npos is the position
// of the name identifier.
//
// TODO(mdempsky): I suspect there's no need for separate fpos and
// npos.
func NewFunc(fpos, npos src.XPos, sym *types.Sym, typ *types.Type) *Func {
name := NewNameAt(npos, sym, typ)
name.Class = PFUNC
sym.SetFunc(true)
fn := &Func{Nname: name}
fn.pos = fpos
fn.op = ODCLFUNC
// Most functions are ABIInternal. The importer or symabis
// pass may override this.
f.ABI = obj.ABIInternal
return f
fn.ABI = obj.ABIInternal
fn.SetTypecheck(1)
name.Func = fn
return fn
}
func (f *Func) isStmt() {}
@ -318,16 +333,6 @@ func FuncSymName(s *types.Sym) string {
return s.Name + "·f"
}
// MarkFunc marks a node as a function.
func MarkFunc(n *Name) {
if n.Op() != ONAME || n.Class != Pxxx {
base.FatalfAt(n.Pos(), "expected ONAME/Pxxx node, got %v (%v/%v)", n, n.Op(), n.Class)
}
n.Class = PFUNC
n.Sym().SetFunc(true)
}
// ClosureDebugRuntimeCheck applies boilerplate checks for debug flags
// and compiling runtime.
func ClosureDebugRuntimeCheck(clo *ClosureExpr) {
@ -402,24 +407,17 @@ func closureName(outerfn *Func, pos src.XPos) *types.Sym {
// outerfn is the enclosing function, if any. The returned function is
// appending to pkg.Funcs.
func NewClosureFunc(fpos, cpos src.XPos, typ *types.Type, outerfn *Func, pkg *Package) *Func {
fn := NewFunc(fpos)
fn := NewFunc(fpos, fpos, closureName(outerfn, cpos), typ)
fn.SetIsHiddenClosure(outerfn != nil)
name := NewNameAt(fpos, closureName(outerfn, cpos), typ)
MarkFunc(name)
name.Func = fn
name.Defn = fn
fn.Nname = name
clo := &ClosureExpr{Func: fn}
clo.op = OCLOSURE
clo.pos = cpos
fn.OClosure = clo
fn.SetTypecheck(1)
clo.SetType(typ)
clo.SetTypecheck(1)
fn.OClosure = clo
fn.Nname.Defn = fn
pkg.Funcs = append(pkg.Funcs, fn)
return fn

View File

@ -750,12 +750,22 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index, implicits, explicits []*types.Typ
if sym.Name == "init" {
sym = Renameinit()
}
name := do(ir.ONAME, true)
setType(name, r.signature(nil))
name.Func = ir.NewFunc(r.pos())
name.Func.Nname = name
name.Func.SetTypecheck(1)
npos := r.pos()
setBasePos(npos)
r.typeParamNames()
typ := r.signature(nil)
fpos := r.pos()
fn := ir.NewFunc(fpos, npos, sym, typ)
name := fn.Nname
if !sym.IsBlank() {
if sym.Def != nil {
base.FatalfAt(name.Pos(), "already have a definition for %v", name)
}
assert(sym.Def == nil)
sym.Def = name
}
if r.hasTypeParams() {
name.Func.SetDupok(true)
@ -990,17 +1000,15 @@ func (r *reader) typeParamNames() {
func (r *reader) method(rext *reader) *types.Field {
r.Sync(pkgbits.SyncMethod)
pos := r.pos()
npos := r.pos()
_, sym := r.selector()
r.typeParamNames()
_, recv := r.param()
typ := r.signature(recv)
name := ir.NewNameAt(pos, ir.MethodSym(recv.Type, sym), typ)
name.Func = ir.NewFunc(r.pos())
name.Func.Nname = name
name.Func.SetTypecheck(1)
fpos := r.pos()
fn := ir.NewFunc(fpos, npos, ir.MethodSym(recv.Type, sym), typ)
name := fn.Nname
if r.hasTypeParams() {
name.Func.SetDupok(true)
@ -1062,9 +1070,6 @@ func (dict *readerDict) hasTypeParams() bool {
func (r *reader) funcExt(name *ir.Name, method *types.Sym) {
r.Sync(pkgbits.SyncFuncExt)
name.Class = 0 // so MarkFunc doesn't complain
ir.MarkFunc(name)
fn := name.Func
// XXX: Workaround because linker doesn't know how to copy Pos.
@ -3447,9 +3452,7 @@ func unifiedInlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.Inlined
r := pri.asReader(pkgbits.RelocBody, pkgbits.SyncFuncBody)
// TODO(mdempsky): This still feels clumsy. Can we do better?
tmpfn := ir.NewFunc(fn.Pos())
tmpfn.Nname = ir.NewNameAt(fn.Nname.Pos(), callerfn.Sym(), fn.Type())
tmpfn.SetTypecheck(1)
tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), callerfn.Sym(), fn.Type())
tmpfn.Closgen = callerfn.Closgen
defer func() { callerfn.Closgen = tmpfn.Closgen }()
@ -3623,9 +3626,7 @@ func expandInline(fn *ir.Func, pri pkgReaderIndex) {
fndcls := len(fn.Dcl)
topdcls := len(typecheck.Target.Funcs)
tmpfn := ir.NewFunc(fn.Pos())
tmpfn.Nname = ir.NewNameAt(fn.Nname.Pos(), fn.Sym(), fn.Type())
tmpfn.SetTypecheck(1)
tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), fn.Sym(), fn.Type())
tmpfn.ClosureVars = fn.ClosureVars
{
@ -3860,18 +3861,9 @@ func wrapMethodValue(recvType *types.Type, method *types.Field, target *ir.Packa
func newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field) *ir.Func {
sig := newWrapperType(wrapper, method)
fn := ir.NewFunc(pos)
fn := ir.NewFunc(pos, pos, sym, sig)
fn.SetDupok(true) // TODO(mdempsky): Leave unset for local, non-generic wrappers?
name := ir.NewNameAt(pos, sym, sig)
ir.MarkFunc(name)
name.Func = fn
name.Defn = fn
fn.Nname = name
setType(name, sig)
fn.SetTypecheck(1)
// TODO(mdempsky): De-duplicate with similar logic in funcargs.
defParams := func(class ir.Class, params *types.Type) {
for _, param := range params.FieldSlice() {
@ -3909,6 +3901,7 @@ func finishWrapperFunc(fn *ir.Func, target *ir.Package) {
}
})
fn.Nname.Defn = fn
target.Funcs = append(target.Funcs, fn)
}

View File

@ -39,8 +39,7 @@ func MakeInit() {
fn.SetIsPackageInit(true)
// Outline (if legal/profitable) global map inits.
newfuncs := []*ir.Func{}
nf, newfuncs = staticinit.OutlineMapInits(nf)
nf, newfuncs := staticinit.OutlineMapInits(nf)
// Suppress useless "can inline" diagnostics.
// Init functions are only called dynamically.
@ -55,17 +54,10 @@ func MakeInit() {
ir.WithFunc(fn, func() {
typecheck.Stmts(nf)
})
typecheck.Target.Funcs = append(typecheck.Target.Funcs, fn)
if base.Debug.WrapGlobalMapDbg > 1 {
fmt.Fprintf(os.Stderr, "=-= len(newfuncs) is %d for %v\n",
len(newfuncs), fn)
}
for _, nfn := range newfuncs {
if base.Debug.WrapGlobalMapDbg > 1 {
fmt.Fprintf(os.Stderr, "=-= add to target.decls %v\n", nfn)
}
typecheck.Target.Funcs = append(typecheck.Target.Funcs, nfn)
}
// Prepend to Inits, so it runs first, before any user-declared init
// functions.
@ -131,13 +123,14 @@ func MakeTask() {
// Call runtime.asanregisterglobals function to poison redzones.
// runtime.asanregisterglobals(unsafe.Pointer(&globals[0]), ni)
asanf := ir.NewNameAt(base.Pos, ir.Pkgs.Runtime.Lookup("asanregisterglobals"),
//
// TODO(mdempsky): Move into typecheck builtins.
asanf := ir.NewFunc(src.NoXPos, src.NoXPos, ir.Pkgs.Runtime.Lookup("asanregisterglobals"),
types.NewSignature(nil, []*types.Field{
types.NewField(base.Pos, nil, types.Types[types.TUNSAFEPTR]),
types.NewField(base.Pos, nil, types.Types[types.TUINTPTR]),
}, nil))
ir.MarkFunc(asanf)
asancall := ir.NewCallExpr(base.Pos, ir.OCALL, asanf, nil)
asancall := ir.NewCallExpr(base.Pos, ir.OCALL, asanf.Nname, nil)
asancall.Args.Append(typecheck.ConvNop(typecheck.NodAddr(
ir.NewIndexExpr(base.Pos, globals, ir.NewInt(base.Pos, 0))), types.Types[types.TUNSAFEPTR]))
asancall.Args.Append(typecheck.DefaultLit(ir.NewInt(base.Pos, int64(ni)), types.Types[types.TUINTPTR]))
@ -148,7 +141,6 @@ func MakeTask() {
typecheck.Stmts(fnInit.Body)
ir.CurFunc = nil
typecheck.Target.Funcs = append(typecheck.Target.Funcs, fnInit)
typecheck.Target.Inits = append(typecheck.Target.Inits, fnInit)
}
}

View File

@ -243,7 +243,6 @@ func hashFunc(t *types.Type) *ir.Func {
})
fn.SetNilCheckDisabled(true)
typecheck.Target.Funcs = append(typecheck.Target.Funcs, fn)
return fn
}
@ -632,7 +631,6 @@ func eqFunc(t *types.Type) *ir.Func {
// neither of which can be nil, and our comparisons
// are shallow.
fn.SetNilCheckDisabled(true)
typecheck.Target.Funcs = append(typecheck.Target.Funcs, fn)
return fn
}

View File

@ -55,8 +55,7 @@ type Conf struct {
func (c *Conf) Frontend() Frontend {
if c.fe == nil {
f := ir.NewFunc(src.NoXPos)
f.Nname = ir.NewNameAt(f.Pos(), &types.Sym{
f := ir.NewFunc(src.NoXPos, src.NoXPos, &types.Sym{
Pkg: types.NewPkg("my/import/path", "path"),
Name: "function",
}, nil)

View File

@ -327,8 +327,6 @@ func makeABIWrapper(f *ir.Func, wrapperABI obj.ABI) {
ir.CurFunc = fn
typecheck.Stmts(fn.Body)
typecheck.Target.Funcs = append(typecheck.Target.Funcs, fn)
// Restore previous context.
base.Pos = savepos
typecheck.DeclContext = savedclcontext

View File

@ -18,11 +18,7 @@ import (
var DeclContext ir.Class = ir.PEXTERN // PEXTERN/PAUTO
func DeclFunc(sym *types.Sym, recv *ir.Field, params, results []*ir.Field) *ir.Func {
fn := ir.NewFunc(base.Pos)
fn.Nname = ir.NewNameAt(base.Pos, sym, nil)
fn.Nname.Func = fn
fn.Nname.Defn = fn
ir.MarkFunc(fn.Nname)
fn := ir.NewFunc(base.Pos, base.Pos, sym, nil)
StartFuncBody(fn)
var recv1 *types.Field
@ -32,9 +28,12 @@ func DeclFunc(sym *types.Sym, recv *ir.Field, params, results []*ir.Field) *ir.F
typ := types.NewSignature(recv1, declareParams(fn, ir.PPARAM, params), declareParams(fn, ir.PPARAMOUT, results))
checkdupfields("argument", typ.Recvs().FieldSlice(), typ.Params().FieldSlice(), typ.Results().FieldSlice())
fn.Nname.SetType(typ)
fn.Nname.SetTypecheck(1)
fn.SetTypecheck(1)
fn.Nname.Defn = fn
Target.Funcs = append(Target.Funcs, fn)
return fn
}

View File

@ -12,38 +12,22 @@ import (
)
// importfunc declares symbol s as an imported function with type t.
// ipkg is the package being imported.
func importfunc(pos src.XPos, s *types.Sym, t *types.Type) *ir.Name {
n := importobj(pos, s, ir.ONAME, ir.PFUNC, t)
n.Func = ir.NewFunc(pos)
n.Func.Nname = n
return n
}
// importobj declares symbol s as an imported object representable by op.
// ipkg is the package being imported.
func importobj(pos src.XPos, s *types.Sym, op ir.Op, ctxt ir.Class, t *types.Type) *ir.Name {
n := importsym(pos, s, op, ctxt)
n.SetType(t)
if ctxt == ir.PFUNC {
n.Sym().SetFunc(true)
}
return n
}
func importsym(pos src.XPos, s *types.Sym, op ir.Op, ctxt ir.Class) *ir.Name {
if n := s.PkgDef(); n != nil {
base.Fatalf("importsym of symbol that already exists: %v", n)
}
n := ir.NewDeclNameAt(pos, op, s)
n.Class = ctxt // TODO(mdempsky): Move this into NewDeclNameAt too?
s.SetPkgDef(n)
return n
func importfunc(s *types.Sym, t *types.Type) {
fn := ir.NewFunc(src.NoXPos, src.NoXPos, s, t)
importsym(fn.Nname)
}
// importvar declares symbol s as an imported variable with type t.
// ipkg is the package being imported.
func importvar(pos src.XPos, s *types.Sym, t *types.Type) *ir.Name {
return importobj(pos, s, ir.ONAME, ir.PEXTERN, t)
func importvar(s *types.Sym, t *types.Type) {
n := ir.NewNameAt(src.NoXPos, s, t)
n.Class = ir.PEXTERN
importsym(n)
}
func importsym(name *ir.Name) {
sym := name.Sym()
if sym.Def != nil {
base.Fatalf("importsym of symbol that already exists: %v", sym.Def)
}
sym.Def = name
}

View File

@ -9,7 +9,6 @@ import (
"cmd/compile/internal/ir"
"cmd/compile/internal/types"
"cmd/internal/obj"
"cmd/internal/src"
)
func LookupRuntime(name string) *ir.Name {
@ -74,9 +73,9 @@ func InitRuntime() {
typ := typs[d.typ]
switch d.tag {
case funcTag:
importfunc(src.NoXPos, sym, typ)
importfunc(sym, typ)
case varTag:
importvar(src.NoXPos, sym, typ)
importvar(sym, typ)
default:
base.Fatalf("unhandled declaration tag %v", d.tag)
}
@ -110,9 +109,9 @@ func InitCoverage() {
typ := typs[d.typ]
switch d.tag {
case funcTag:
importfunc(src.NoXPos, sym, typ)
importfunc(sym, typ)
case varTag:
importvar(src.NoXPos, sym, typ)
importvar(sym, typ)
default:
base.Fatalf("unhandled declaration tag %v", d.tag)
}

View File

@ -19,7 +19,7 @@ import (
// Function collecting autotmps generated during typechecking,
// to be included in the package-level init function.
var InitTodoFunc = ir.NewFunc(base.Pos)
var InitTodoFunc = ir.NewFunc(base.Pos, base.Pos, Lookup("$InitTodo"), types.NewSignature(nil, nil, nil))
var (
NeedRuntimeType = func(*types.Type) {}

View File

@ -1,11 +0,0 @@
// Copyright 2017 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 types
// PkgDef returns the definition associated with s at package scope.
func (s *Sym) PkgDef() Object { return s.Def }
// SetPkgDef sets the definition associated with s at package scope.
func (s *Sym) SetPkgDef(n Object) { s.Def = n }