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 {
}
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)
}