mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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>
This commit is contained in:
parent
ea3054aecc
commit
864b54e2c3
2 changed files with 30 additions and 7 deletions
|
|
@ -357,16 +357,19 @@ func geneq(t *types.Type) *obj.LSym {
|
||||||
|
|
||||||
func eqFunc(t *types.Type) *ir.Func {
|
func eqFunc(t *types.Type) *ir.Func {
|
||||||
// Autogenerate code for equality of structs and arrays.
|
// 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
|
base.Pos = base.AutogeneratedPos // less confusing than end of input
|
||||||
typecheck.DeclContext = ir.PEXTERN
|
typecheck.DeclContext = ir.PEXTERN
|
||||||
|
|
||||||
// func sym(p, q *T) bool
|
// func sym(p, q *T) bool
|
||||||
sym := TypeSymPrefix(".eq", t)
|
|
||||||
fn := typecheck.DeclFunc(sym, nil,
|
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("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])},
|
[]*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)
|
np := ir.AsNode(fn.Type().Params().Field(0).Nname)
|
||||||
nq := ir.AsNode(fn.Type().Params().Field(1).Nname)
|
nq := ir.AsNode(fn.Type().Params().Field(1).Nname)
|
||||||
nr := ir.AsNode(fn.Type().Results().Field(0).Nname)
|
nr := ir.AsNode(fn.Type().Results().Field(0).Nname)
|
||||||
|
|
@ -554,9 +557,9 @@ func eqFunc(t *types.Type) *ir.Func {
|
||||||
fn.SetDupok(true)
|
fn.SetDupok(true)
|
||||||
typecheck.Func(fn)
|
typecheck.Func(fn)
|
||||||
|
|
||||||
ir.CurFunc = fn
|
ir.WithFunc(fn, func() {
|
||||||
typecheck.Stmts(fn.Body)
|
typecheck.Stmts(fn.Body)
|
||||||
ir.CurFunc = nil
|
})
|
||||||
|
|
||||||
// Disable checknils while compiling this code.
|
// Disable checknils while compiling this code.
|
||||||
// We are comparing a struct or an array,
|
// We are comparing a struct or an array,
|
||||||
|
|
@ -567,6 +570,22 @@ func eqFunc(t *types.Type) *ir.Func {
|
||||||
return fn
|
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 {
|
func anyCall(fn *ir.Func) bool {
|
||||||
return ir.Any(fn, func(n ir.Node) bool {
|
return ir.Any(fn, func(n ir.Node) bool {
|
||||||
// TODO(rsc): No methods?
|
// TODO(rsc): No methods?
|
||||||
|
|
|
||||||
|
|
@ -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)
|
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 := ir.NewCallExpr(base.Pos, ir.OCALL, fn, nil)
|
||||||
call.Args.Append(typecheck.NodAddr(cmpl))
|
call.Args.Append(typecheck.NodAddr(cmpl))
|
||||||
call.Args.Append(typecheck.NodAddr(cmpr))
|
call.Args.Append(typecheck.NodAddr(cmpr))
|
||||||
if needsize {
|
if needsLength {
|
||||||
call.Args.Append(ir.NewInt(t.Size()))
|
call.Args.Append(ir.NewInt(t.Size()))
|
||||||
}
|
}
|
||||||
res := ir.Node(call)
|
res := ir.Node(call)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue