cmd/compile: generate type equal func during walk
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>
diff --git a/src/cmd/compile/internal/reflectdata/alg.go b/src/cmd/compile/internal/reflectdata/alg.go
index 1a8b768..4577e9c 100644
--- a/src/cmd/compile/internal/reflectdata/alg.go
+++ b/src/cmd/compile/internal/reflectdata/alg.go
@@ -357,16 +357,19 @@
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 @@
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 @@
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?
diff --git a/src/cmd/compile/internal/walk/compare.go b/src/cmd/compile/internal/walk/compare.go
index 0382894..87987b0 100644
--- a/src/cmd/compile/internal/walk/compare.go
+++ b/src/cmd/compile/internal/walk/compare.go
@@ -186,11 +186,15 @@
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)