From: Matthew Dempsky Date: Sat, 19 Aug 2023 00:43:15 +0000 (-0700) Subject: cmd/compile/internal/typecheck: refactor and simplify DeclFunc X-Git-Tag: go1.22rc1~1191 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=009ca22fe2936c9a7a5a9e5364fe061688b27697;p=gostls13.git cmd/compile/internal/typecheck: refactor and simplify DeclFunc This CL refactors typecheck.DeclFunc to require the caller to have already constructed the ir.Func and signature type using ir.NewFunc and types.NewSignature, and simplifies typecheck.DeclFunc to simply return the slices of param and results ONAMEs. typecheck.DeclFunc was the last reason that ir.Field still exists, so this CL also gets rid of that. Change-Id: Ib398420bac2fd135a235810b8af1635fa754965c Reviewed-on: https://go-review.googlesource.com/c/go/+/520977 Run-TryBot: Matthew Dempsky Auto-Submit: Matthew Dempsky TryBot-Result: Gopher Robot Reviewed-by: Dmitri Shuralyov Reviewed-by: Cuong Manh Le --- diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go index 00d0a1d634..7db76c1427 100644 --- a/src/cmd/compile/internal/ir/type.go +++ b/src/cmd/compile/internal/ir/type.go @@ -8,31 +8,10 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/types" "cmd/internal/src" - "fmt" ) // Calling TypeNode converts a *types.Type to a Node shell. -// A Field is a declared function parameter. -// It is not a Node. -type Field struct { - Pos src.XPos - Sym *types.Sym - Type *types.Type - IsDDD bool -} - -func NewField(pos src.XPos, sym *types.Sym, typ *types.Type) *Field { - return &Field{Pos: pos, Sym: sym, Type: typ} -} - -func (f *Field) String() string { - if f.Sym != nil { - return fmt.Sprintf("%v %v", f.Sym, f.Type) - } - return fmt.Sprint(f.Type) -} - // A typeNode is a Node wrapper for type t. type typeNode struct { miniNode diff --git a/src/cmd/compile/internal/pkginit/init.go b/src/cmd/compile/internal/pkginit/init.go index daf26150a4..4d4896d447 100644 --- a/src/cmd/compile/internal/pkginit/init.go +++ b/src/cmd/compile/internal/pkginit/init.go @@ -28,9 +28,13 @@ func MakeInit() { } // Make a function that contains all the initialization statements. - base.Pos = nf[0].Pos() // prolog/epilog gets line number of first init stmt - initializers := typecheck.Lookup("init") - fn := typecheck.DeclFunc(initializers, nil, nil, nil) + pos := nf[0].Pos() // prolog/epilog gets line number of first init stmt + base.Pos = pos + + sym := typecheck.Lookup("init") + fn := ir.NewFunc(pos, pos, sym, types.NewSignature(nil, nil, nil)) + typecheck.DeclFunc(fn) + for _, dcl := range typecheck.InitTodoFunc.Dcl { dcl.Curfn = fn } @@ -113,9 +117,12 @@ func MakeTask() { ni := len(InstrumentGlobalsMap) if ni != 0 { // Make an init._ function. - base.Pos = base.AutogeneratedPos - name := noder.Renameinit() - fnInit := typecheck.DeclFunc(name, nil, nil, nil) + pos := base.AutogeneratedPos + base.Pos = pos + + sym := noder.Renameinit() + fnInit := ir.NewFunc(pos, pos, sym, types.NewSignature(nil, nil, nil)) + typecheck.DeclFunc(fnInit) // Get an array of instrumented global variables. globals := instrumentGlobals(fnInit) diff --git a/src/cmd/compile/internal/reflectdata/alg.go b/src/cmd/compile/internal/reflectdata/alg.go index 01135de39f..ba2bf85db3 100644 --- a/src/cmd/compile/internal/reflectdata/alg.go +++ b/src/cmd/compile/internal/reflectdata/alg.go @@ -140,21 +140,25 @@ func hashFunc(t *types.Type) *ir.Func { return sym.Def.(*ir.Name).Func } - base.Pos = base.AutogeneratedPos // less confusing than end of input + pos := base.AutogeneratedPos // less confusing than end of input + base.Pos = pos // func sym(p *T, h uintptr) uintptr - args := []*ir.Field{ - ir.NewField(base.Pos, typecheck.Lookup("p"), types.NewPtr(t)), - ir.NewField(base.Pos, typecheck.Lookup("h"), types.Types[types.TUINTPTR]), - } - results := []*ir.Field{ir.NewField(base.Pos, nil, types.Types[types.TUINTPTR])} - - fn := typecheck.DeclFunc(sym, nil, args, results) + fn := ir.NewFunc(pos, pos, sym, types.NewSignature(nil, + []*types.Field{ + types.NewField(pos, typecheck.Lookup("p"), types.NewPtr(t)), + types.NewField(pos, typecheck.Lookup("h"), types.Types[types.TUINTPTR]), + }, + []*types.Field{ + types.NewField(pos, nil, types.Types[types.TUINTPTR]), + }, + )) sym.Def = fn.Nname fn.Pragma |= ir.Noinline // TODO(mdempsky): We need to emit this during the unified frontend instead, to allow inlining. - np := fn.Type().Params().Field(0).Nname.(*ir.Name) - nh := fn.Type().Params().Field(1).Nname.(*ir.Name) + params, _ := typecheck.DeclFunc(fn) + np := params[0] + nh := params[1] switch t.Kind() { case types.TARRAY: @@ -365,19 +369,27 @@ func eqFunc(t *types.Type) *ir.Func { if sym.Def != nil { return sym.Def.(*ir.Name).Func } - base.Pos = base.AutogeneratedPos // less confusing than end of input + + pos := base.AutogeneratedPos // less confusing than end of input + base.Pos = pos // func sym(p, q *T) bool - fn := typecheck.DeclFunc(sym, nil, - []*ir.Field{ir.NewField(base.Pos, typecheck.Lookup("p"), types.NewPtr(t)), ir.NewField(base.Pos, typecheck.Lookup("q"), types.NewPtr(t))}, - []*ir.Field{ir.NewField(base.Pos, typecheck.Lookup("r"), types.Types[types.TBOOL])}, - ) + fn := ir.NewFunc(pos, pos, sym, types.NewSignature(nil, + []*types.Field{ + types.NewField(pos, typecheck.Lookup("p"), types.NewPtr(t)), + types.NewField(pos, typecheck.Lookup("q"), types.NewPtr(t)), + }, + []*types.Field{ + types.NewField(pos, typecheck.Lookup("r"), types.Types[types.TBOOL]), + }, + )) sym.Def = fn.Nname fn.Pragma |= ir.Noinline // TODO(mdempsky): We need to emit this during the unified frontend instead, to allow inlining. - np := fn.Type().Params().Field(0).Nname.(*ir.Name) - nq := fn.Type().Params().Field(1).Nname.(*ir.Name) - nr := fn.Type().Results().Field(0).Nname.(*ir.Name) + params, results := typecheck.DeclFunc(fn) + np := params[0] + nq := params[1] + nr := results[0] // Label to jump to if an equality test fails. neq := typecheck.AutoLabel(".neq") diff --git a/src/cmd/compile/internal/ssagen/abi.go b/src/cmd/compile/internal/ssagen/abi.go index 6a6171a0ed..cd01fdacbe 100644 --- a/src/cmd/compile/internal/ssagen/abi.go +++ b/src/cmd/compile/internal/ssagen/abi.go @@ -239,7 +239,8 @@ func makeABIWrapper(f *ir.Func, wrapperABI obj.ABI) { savepos := base.Pos savedcurfn := ir.CurFunc - base.Pos = base.AutogeneratedPos + pos := base.AutogeneratedPos + base.Pos = pos // At the moment we don't support wrapping a method, we'd need machinery // below to handle the receiver. Panic if we see this scenario. @@ -250,10 +251,12 @@ func makeABIWrapper(f *ir.Func, wrapperABI obj.ABI) { } // Reuse f's types.Sym to create a new ODCLFUNC/function. - fn := typecheck.DeclFunc(f.Nname.Sym(), nil, - typecheck.NewFuncParams(ft.Params(), true), - typecheck.NewFuncParams(ft.Results(), false)) + // TODO(mdempsky): Means we can't set sym.Def in Declfunc, ugh. + fn := ir.NewFunc(pos, pos, f.Sym(), types.NewSignature(nil, + typecheck.NewFuncParams(ft.Params().FieldSlice(), true), + typecheck.NewFuncParams(ft.Results().FieldSlice(), false))) fn.ABI = wrapperABI + typecheck.DeclFunc(fn) fn.SetABIWrapper(true) fn.SetDupok(true) diff --git a/src/cmd/compile/internal/staticinit/sched.go b/src/cmd/compile/internal/staticinit/sched.go index cc97d2fcf7..52d3d029ad 100644 --- a/src/cmd/compile/internal/staticinit/sched.go +++ b/src/cmd/compile/internal/staticinit/sched.go @@ -1042,7 +1042,9 @@ func tryWrapGlobalMapInit(n ir.Node) (mapvar *ir.Name, genfn *ir.Func, call ir.N // minitsym := typecheck.LookupNum("map.init.", mapinitgen) mapinitgen++ - newfn := typecheck.DeclFunc(minitsym, nil, nil, nil) + + newfn := ir.NewFunc(base.Pos, base.Pos, minitsym, types.NewSignature(nil, nil, nil)) + typecheck.DeclFunc(newfn) if base.Debug.WrapGlobalMapDbg > 0 { fmt.Fprintf(os.Stderr, "=-= generated func is %v\n", newfn) } diff --git a/src/cmd/compile/internal/typecheck/dcl.go b/src/cmd/compile/internal/typecheck/dcl.go index 47b975e3b4..a78aad5abc 100644 --- a/src/cmd/compile/internal/typecheck/dcl.go +++ b/src/cmd/compile/internal/typecheck/dcl.go @@ -6,7 +6,6 @@ package typecheck import ( "fmt" - "internal/types/errors" "sync" "cmd/compile/internal/base" @@ -17,32 +16,36 @@ import ( var funcStack []*ir.Func // stack of previous values of ir.CurFunc -func DeclFunc(sym *types.Sym, recv *ir.Field, params, results []*ir.Field) *ir.Func { - fn := ir.NewFunc(base.Pos, base.Pos, sym, nil) +// DeclFunc creates and returns ONAMEs for the parameters and results +// of the given function. It also sets ir.CurFunc, and adds fn to +// Target.Funcs. +// +// After the caller is done constructing fn, it must call +// FinishFuncBody. +func DeclFunc(fn *ir.Func) (params, results []*ir.Name) { + typ := fn.Type() - funcStack = append(funcStack, ir.CurFunc) - ir.CurFunc = fn - - var recv1 *types.Field - if recv != nil { - recv1 = declareParam(fn, ir.PPARAM, -1, recv) + // Currently, DeclFunc is only used to create normal functions, not + // methods. If a use case for creating methods shows up, we can + // extend it to support those too. + if typ.Recv() != nil { + base.FatalfAt(fn.Pos(), "unexpected receiver parameter") } - 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()) + params = declareParams(fn, ir.PPARAM, typ.Params().FieldSlice()) + results = declareParams(fn, ir.PPARAMOUT, typ.Results().FieldSlice()) - fn.Nname.SetType(typ) - fn.Nname.SetTypecheck(1) + funcStack = append(funcStack, ir.CurFunc) + ir.CurFunc = fn fn.Nname.Defn = fn Target.Funcs = append(Target.Funcs, fn) - return fn + return } -// finish the body. -// called in auto-declaration context. -// returns in extern-declaration context. +// FinishFuncBody restores ir.CurFunc to its state before the last +// call to DeclFunc. func FinishFuncBody() { funcStack, ir.CurFunc = funcStack[:len(funcStack)-1], funcStack[len(funcStack)-1] } @@ -53,36 +56,15 @@ func CheckFuncStack() { } } -// checkdupfields emits errors for duplicately named fields or methods in -// a list of struct or interface types. -func checkdupfields(what string, fss ...[]*types.Field) { - seen := make(map[*types.Sym]bool) - for _, fs := range fss { - for _, f := range fs { - if f.Sym == nil || f.Sym.IsBlank() { - continue - } - if seen[f.Sym] { - base.ErrorfAt(f.Pos, errors.DuplicateFieldAndMethod, "duplicate %s %s", what, f.Sym.Name) - continue - } - seen[f.Sym] = true - } +func declareParams(fn *ir.Func, ctxt ir.Class, params []*types.Field) []*ir.Name { + names := make([]*ir.Name, len(params)) + for i, param := range params { + names[i] = declareParam(fn, ctxt, i, param) } + return names } -func declareParams(fn *ir.Func, ctxt ir.Class, l []*ir.Field) []*types.Field { - fields := make([]*types.Field, len(l)) - for i, n := range l { - fields[i] = declareParam(fn, ctxt, i, n) - } - return fields -} - -func declareParam(fn *ir.Func, ctxt ir.Class, i int, param *ir.Field) *types.Field { - f := types.NewField(param.Pos, param.Sym, param.Type) - f.SetIsDDD(param.IsDDD) - +func declareParam(fn *ir.Func, ctxt ir.Class, i int, param *types.Field) *ir.Name { sym := param.Sym if ctxt == ir.PPARAMOUT { if sym == nil { @@ -99,11 +81,13 @@ func declareParam(fn *ir.Func, ctxt ir.Class, i int, param *ir.Field) *types.Fie } } - if sym != nil { - f.Nname = fn.NewLocal(param.Pos, sym, ctxt, f.Type) + if sym == nil { + return nil } - return f + name := fn.NewLocal(param.Pos, sym, ctxt, param.Type) + param.Nname = name + return name } // make a new Node off the books. diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 91d05778f1..56ff7a7317 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -26,26 +26,22 @@ func LookupNum(prefix string, n int) *types.Sym { } // Given funarg struct list, return list of fn args. -func NewFuncParams(tl *types.Type, mustname bool) []*ir.Field { - var args []*ir.Field - gen := 0 - for _, t := range tl.Fields().Slice() { - s := t.Sym +func NewFuncParams(origs []*types.Field, mustname bool) []*types.Field { + res := make([]*types.Field, len(origs)) + for i, orig := range origs { + s := orig.Sym if mustname && (s == nil || s.Name == "_") { // invent a name so that we can refer to it in the trampoline - s = LookupNum(".anon", gen) - gen++ + s = LookupNum(".anon", i) } else if s != nil && s.Pkg != types.LocalPkg { // TODO(mdempsky): Preserve original position, name, and package. s = Lookup(s.Name) } - a := ir.NewField(base.Pos, s, t.Type) - a.Pos = t.Pos - a.IsDDD = t.IsDDD() - args = append(args, a) + p := types.NewField(orig.Pos, s, orig.Type) + p.SetIsDDD(orig.IsDDD()) + res[i] = p } - - return args + return res } // NodAddr returns a node representing &n at base.Pos.