mirror of
https://github.com/golang/go
synced 2024-11-23 19:50:06 -07:00
cmd/compile: refactor out eqinterface
Refactor out creating the two Nodes needed to check interface equality. Preliminary work to other optimizations. Passes toolstash-check. Change-Id: Id6b39e8e78f07289193423d0ef905d70826acf89 Reviewed-on: https://go-review.googlesource.com/c/go/+/230206 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
5029c3671d
commit
f4e13b83aa
@ -699,6 +699,44 @@ func eqstring(s, t *Node) (eqlen, eqmem *Node) {
|
||||
return cmp, call
|
||||
}
|
||||
|
||||
// eqinterface returns the nodes
|
||||
// s.tab == t.tab (or s.typ == t.typ, as appropriate)
|
||||
// and
|
||||
// ifaceeq(s.tab, s.data, t.data) (or efaceeq(s.typ, s.data, t.data), as appropriate)
|
||||
// which can be used to construct interface equality comparison.
|
||||
// eqtab must be evaluated before eqdata, and shortcircuiting is required.
|
||||
func eqinterface(s, t *Node) (eqtab, eqdata *Node) {
|
||||
if !types.Identical(s.Type, t.Type) {
|
||||
Fatalf("eqinterface %v %v", s.Type, t.Type)
|
||||
}
|
||||
// func ifaceeq(tab *uintptr, x, y unsafe.Pointer) (ret bool)
|
||||
// func efaceeq(typ *uintptr, x, y unsafe.Pointer) (ret bool)
|
||||
var fn *Node
|
||||
if s.Type.IsEmptyInterface() {
|
||||
fn = syslook("efaceeq")
|
||||
} else {
|
||||
fn = syslook("ifaceeq")
|
||||
}
|
||||
|
||||
stab := nod(OITAB, s, nil)
|
||||
ttab := nod(OITAB, t, nil)
|
||||
sdata := nod(OIDATA, s, nil)
|
||||
tdata := nod(OIDATA, t, nil)
|
||||
sdata.Type = types.Types[TUNSAFEPTR]
|
||||
tdata.Type = types.Types[TUNSAFEPTR]
|
||||
sdata.SetTypecheck(1)
|
||||
tdata.SetTypecheck(1)
|
||||
|
||||
call := nod(OCALL, fn, nil)
|
||||
call.List.Append(stab, sdata, tdata)
|
||||
call = typecheck(call, ctxExpr|ctxMultiOK)
|
||||
|
||||
cmp := nod(OEQ, stab, ttab)
|
||||
cmp = typecheck(cmp, ctxExpr)
|
||||
cmp.Type = types.Types[TBOOL]
|
||||
return cmp, call
|
||||
}
|
||||
|
||||
// eqmem returns the node
|
||||
// memequal(&p.field, &q.field [, size])
|
||||
func eqmem(p *Node, q *Node, field *types.Sym, size int64) *Node {
|
||||
|
@ -3379,36 +3379,15 @@ func tracecmpArg(n *Node, t *types.Type, init *Nodes) *Node {
|
||||
}
|
||||
|
||||
func walkcompareInterface(n *Node, init *Nodes) *Node {
|
||||
// ifaceeq(i1 any-1, i2 any-2) (ret bool);
|
||||
if !types.Identical(n.Left.Type, n.Right.Type) {
|
||||
Fatalf("ifaceeq %v %v %v", n.Op, n.Left.Type, n.Right.Type)
|
||||
}
|
||||
var fn *Node
|
||||
if n.Left.Type.IsEmptyInterface() {
|
||||
fn = syslook("efaceeq")
|
||||
} else {
|
||||
fn = syslook("ifaceeq")
|
||||
}
|
||||
|
||||
n.Right = cheapexpr(n.Right, init)
|
||||
n.Left = cheapexpr(n.Left, init)
|
||||
lt := nod(OITAB, n.Left, nil)
|
||||
rt := nod(OITAB, n.Right, nil)
|
||||
ld := nod(OIDATA, n.Left, nil)
|
||||
rd := nod(OIDATA, n.Right, nil)
|
||||
ld.Type = types.Types[TUNSAFEPTR]
|
||||
rd.Type = types.Types[TUNSAFEPTR]
|
||||
ld.SetTypecheck(1)
|
||||
rd.SetTypecheck(1)
|
||||
call := mkcall1(fn, n.Type, init, lt, ld, rd)
|
||||
|
||||
// Check itable/type before full compare.
|
||||
// Note: short-circuited because order matters.
|
||||
eqtab, eqdata := eqinterface(n.Left, n.Right)
|
||||
var cmp *Node
|
||||
if n.Op == OEQ {
|
||||
cmp = nod(OANDAND, nod(OEQ, lt, rt), call)
|
||||
cmp = nod(OANDAND, eqtab, eqdata)
|
||||
} else {
|
||||
cmp = nod(OOROR, nod(ONE, lt, rt), nod(ONOT, call, nil))
|
||||
eqtab.Op = ONE
|
||||
cmp = nod(OOROR, eqtab, nod(ONOT, eqdata, nil))
|
||||
}
|
||||
return finishcompare(n, cmp, init)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user