]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: generate type equal func during walk
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Wed, 28 Sep 2022 05:30:46 +0000 (12:30 +0700)
committerCuong Manh Le <cuong.manhle.vn@gmail.com>
Sat, 4 Feb 2023 07:02:44 +0000 (07:02 +0000)
So we don't generate ONAME node with nil Func.

Do not pass toolstash-check because the CL changes the order of
compiling functions.

Change-Id: Ib967328f36b8c59a5525445667103c0c80ccdc82
Reviewed-on: https://go-review.googlesource.com/c/go/+/436436
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>

src/cmd/compile/internal/reflectdata/alg.go
src/cmd/compile/internal/walk/compare.go

index 1a8b76851c06aaf46e4519803c95e44c730b73fe..4577e9cfc4acf5e0ea385d1236b7dda9df5d283a 100644 (file)
@@ -357,16 +357,19 @@ func geneq(t *types.Type) *obj.LSym {
 
 func eqFunc(t *types.Type) *ir.Func {
        // Autogenerate code for equality of structs and arrays.
-
+       sym := TypeSymPrefix(".eq", t)
+       if sym.Def != nil {
+               return sym.Def.(*ir.Name).Func
+       }
        base.Pos = base.AutogeneratedPos // less confusing than end of input
        typecheck.DeclContext = ir.PEXTERN
 
        // func sym(p, q *T) bool
-       sym := TypeSymPrefix(".eq", t)
        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])},
        )
+       sym.Def = fn.Nname
        np := ir.AsNode(fn.Type().Params().Field(0).Nname)
        nq := ir.AsNode(fn.Type().Params().Field(1).Nname)
        nr := ir.AsNode(fn.Type().Results().Field(0).Nname)
@@ -554,9 +557,9 @@ func eqFunc(t *types.Type) *ir.Func {
        fn.SetDupok(true)
        typecheck.Func(fn)
 
-       ir.CurFunc = fn
-       typecheck.Stmts(fn.Body)
-       ir.CurFunc = nil
+       ir.WithFunc(fn, func() {
+               typecheck.Stmts(fn.Body)
+       })
 
        // Disable checknils while compiling this code.
        // We are comparing a struct or an array,
@@ -567,6 +570,22 @@ func eqFunc(t *types.Type) *ir.Func {
        return fn
 }
 
+// EqFor returns ONAME node represents type t's equal function, and a boolean
+// to indicates whether a length needs to be passed when calling the function.
+func EqFor(t *types.Type) (ir.Node, bool) {
+       switch a, _ := types.AlgType(t); a {
+       case types.AMEM:
+               n := typecheck.LookupRuntime("memequal")
+               n = typecheck.SubstArgTypes(n, t, t)
+               return n, true
+       case types.ASPECIAL:
+               fn := eqFunc(t)
+               return fn.Nname, false
+       }
+       base.Fatalf("EqFor %v", t)
+       return nil, false
+}
+
 func anyCall(fn *ir.Func) bool {
        return ir.Any(fn, func(n ir.Node) bool {
                // TODO(rsc): No methods?
index 0382894f386991e1cf70c12179d05e7128ea85f6..87987b09a69ef5ac49c54ed9b58ad027dd11053c 100644 (file)
@@ -186,11 +186,15 @@ func walkCompare(n *ir.BinaryExpr, init *ir.Nodes) ir.Node {
                        base.Fatalf("arguments of comparison must be lvalues - %v %v", cmpl, cmpr)
                }
 
-               fn, needsize := eqFor(t)
+               // Should only arrive here with large memory or
+               // a struct/array containing a non-memory field/element.
+               // Small memory is handled inline, and single non-memory
+               // is handled by walkCompare.
+               fn, needsLength := reflectdata.EqFor(t)
                call := ir.NewCallExpr(base.Pos, ir.OCALL, fn, nil)
                call.Args.Append(typecheck.NodAddr(cmpl))
                call.Args.Append(typecheck.NodAddr(cmpr))
-               if needsize {
+               if needsLength {
                        call.Args.Append(ir.NewInt(t.Size()))
                }
                res := ir.Node(call)