]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/typecheck: refactor and simplify DeclFunc
authorMatthew Dempsky <mdempsky@google.com>
Sat, 19 Aug 2023 00:43:15 +0000 (17:43 -0700)
committerGopher Robot <gobot@golang.org>
Sun, 20 Aug 2023 05:56:49 +0000 (05:56 +0000)
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 <mdempsky@google.com>
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
src/cmd/compile/internal/ir/type.go
src/cmd/compile/internal/pkginit/init.go
src/cmd/compile/internal/reflectdata/alg.go
src/cmd/compile/internal/ssagen/abi.go
src/cmd/compile/internal/staticinit/sched.go
src/cmd/compile/internal/typecheck/dcl.go
src/cmd/compile/internal/typecheck/subr.go

index 00d0a1d634fe96160e4b6317d7a8c0c6e42bdca9..7db76c1427f4bdb6995525810eafed3d600eda29 100644 (file)
@@ -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
index daf26150a406e7c2704021a8702d00e8cadb782a..4d4896d447d818fb8f969b70f9ea0c876fd67a81 100644 (file)
@@ -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)
index 01135de39f4545991eb14f269ddce3b0f36ce66d..ba2bf85db34c9366853d363ad170b43704344e88 100644 (file)
@@ -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")
index 6a6171a0ed652ca73ecfb8358c29f6d105076355..cd01fdacbe4499cf33f1de1320dcfc7debde381d 100644 (file)
@@ -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)
index cc97d2fcf7a7ebc7caec74c12271717ef80889fe..52d3d029ad06e884c1e66d34659f3cb1e69a9956 100644 (file)
@@ -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)
        }
index 47b975e3b41b98af5d18975c3550dd80cef20f34..a78aad5abc7b2ff8a7f9a7572c1c862117d0b858 100644 (file)
@@ -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.
index 91d05778f138d260332516452e91aa2607c337d5..56ff7a73179051c86ef2ba7d8743769491a7e5db 100644 (file)
@@ -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.