cmd/internal/gc: clean up bgen
This cleanup is in anticipation of implementing
jump-free booleans (CL 2284) and zero-aware
comparisons (issue 10381).
No functional changes. Passes toolstash -cmp.
Change-Id: I50f394c60fa2927e177d7fc85b75085060a9e912
Reviewed-on: https://go-review.googlesource.com/8738
Reviewed-by: Russ Cox <rsc@golang.org>
diff --git a/src/cmd/internal/gc/cgen.go b/src/cmd/internal/gc/cgen.go
index 2ceddc9..8c7cb0e 100644
--- a/src/cmd/internal/gc/cgen.go
+++ b/src/cmd/internal/gc/cgen.go
@@ -345,18 +345,13 @@
Dump("cgen-res", res)
Fatal("cgen: unknown op %v", Nconv(n, obj.FmtShort|obj.FmtSign))
- // these call bgen to get a bool value
- case OOROR,
- OANDAND,
- OEQ,
- ONE,
- OLT,
- OLE,
- OGE,
- OGT,
+ // these call bgen to get a bool value
+ case OOROR, OANDAND,
+ OEQ, ONE,
+ OLT, OLE,
+ OGE, OGT,
ONOT:
p1 := Gbranch(obj.AJMP, nil, 0)
-
p2 := Pc
Thearch.Gmove(Nodbool(true), res)
p3 := Gbranch(obj.AJMP, nil, 0)
@@ -1639,22 +1634,22 @@
a.Type = n.Type
}
-/*
- * generate:
- * if(n == true) goto to;
- */
-func Bgen(n *Node, true_ bool, likely int, to *obj.Prog) {
+// Bgen generates code for branches:
+//
+// if n == wantTrue {
+// goto to
+// }
+func Bgen(n *Node, wantTrue bool, likely int, to *obj.Prog) {
if Debug['g'] != 0 {
- Dump("\nbgen", n)
+ fmt.Printf("\nbgen wantTrue=%t likely=%d to=%v\n", wantTrue, likely, to)
+ Dump("bgen", n)
}
if n == nil {
n = Nodbool(true)
}
- if n.Ninit != nil {
- Genlist(n.Ninit)
- }
+ Genlist(n.Ninit)
if n.Type == nil {
Convlit(&n, Types[TBOOL])
@@ -1663,8 +1658,7 @@
}
}
- et := int(n.Type.Etype)
- if et != TBOOL {
+ if n.Type.Etype != TBOOL {
Yyerror("cgen: bad type %v for %v", Tconv(n.Type, 0), Oconv(int(n.Op), 0))
Patch(Thearch.Gins(obj.AEND, nil, nil), to)
return
@@ -1672,204 +1666,172 @@
for n.Op == OCONVNOP {
n = n.Left
- if n.Ninit != nil {
- Genlist(n.Ninit)
- }
+ Genlist(n.Ninit)
}
if Thearch.Bgen_float != nil && n.Left != nil && Isfloat[n.Left.Type.Etype] {
- Thearch.Bgen_float(n, bool2int(true_), likely, to)
+ Thearch.Bgen_float(n, wantTrue, likely, to)
return
}
- var nl *Node
- var nr *Node
switch n.Op {
default:
- goto def
+ var tmp Node
+ Regalloc(&tmp, n.Type, nil)
+ Cgen(n, &tmp)
+ bgenNonZero(&tmp, wantTrue, likely, to)
+ Regfree(&tmp)
+ return
- // need to ask if it is bool?
+ case ONAME:
+ if n.Addable && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' {
+ // no need for a temporary
+ bgenNonZero(n, wantTrue, likely, to)
+ return
+ }
+ var tmp Node
+ Regalloc(&tmp, n.Type, nil)
+ Cgen(n, &tmp)
+ bgenNonZero(&tmp, wantTrue, likely, to)
+ Regfree(&tmp)
+ return
+
case OLITERAL:
- if true_ == n.Val.U.Bval {
+ // n is a constant. If n == wantTrue, jump; otherwise do nothing.
+ if !Isconst(n, CTBOOL) {
+ Fatal("bgen: non-bool const %v\n", Nconv(n, obj.FmtLong))
+ }
+ if wantTrue == n.Val.U.Bval {
Patch(Gbranch(obj.AJMP, nil, likely), to)
}
return
- case ONAME:
- if !n.Addable || Ctxt.Arch.Thechar == '5' || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
- goto def
- }
- var n1 Node
- Nodconst(&n1, n.Type, 0)
- Thearch.Gins(Thearch.Optoas(OCMP, n.Type), n, &n1)
- a := Thearch.Optoas(ONE, n.Type)
- if !true_ {
- a = Thearch.Optoas(OEQ, n.Type)
- }
- Patch(Gbranch(a, n.Type, likely), to)
- return
-
case OANDAND, OOROR:
- if (n.Op == OANDAND) == true_ {
+ if (n.Op == OANDAND) == wantTrue {
p1 := Gbranch(obj.AJMP, nil, 0)
p2 := Gbranch(obj.AJMP, nil, 0)
Patch(p1, Pc)
- Bgen(n.Left, !true_, -likely, p2)
- Bgen(n.Right, !true_, -likely, p2)
+ Bgen(n.Left, !wantTrue, -likely, p2)
+ Bgen(n.Right, !wantTrue, -likely, p2)
p1 = Gbranch(obj.AJMP, nil, 0)
Patch(p1, to)
Patch(p2, Pc)
} else {
- Bgen(n.Left, true_, likely, to)
- Bgen(n.Right, true_, likely, to)
+ Bgen(n.Left, wantTrue, likely, to)
+ Bgen(n.Right, wantTrue, likely, to)
}
+ return
+ case ONOT: // unary
+ if n.Left == nil || n.Left.Type == nil {
+ return
+ }
+ Bgen(n.Left, !wantTrue, likely, to)
return
case OEQ, ONE, OLT, OGT, OLE, OGE:
- nr = n.Right
- if nr == nil || nr.Type == nil {
- return
- }
- fallthrough
-
- case ONOT: // unary
- nl = n.Left
-
- if nl == nil || nl.Type == nil {
+ if n.Left == nil || n.Left.Type == nil || n.Right == nil || n.Right.Type == nil {
return
}
}
- switch n.Op {
- case ONOT:
- Bgen(nl, !true_, likely, to)
- return
+ // n.Op is one of OEQ, ONE, OLT, OGT, OLE, OGE
+ nl := n.Left
+ nr := n.Right
+ a := int(n.Op)
- case OEQ, ONE, OLT, OGT, OLE, OGE:
- a := int(n.Op)
- if !true_ {
- if Isfloat[nr.Type.Etype] {
- // brcom is not valid on floats when NaN is involved.
- p1 := Gbranch(obj.AJMP, nil, 0)
- p2 := Gbranch(obj.AJMP, nil, 0)
- Patch(p1, Pc)
- ll := n.Ninit // avoid re-genning ninit
- n.Ninit = nil
- Bgen(n, true, -likely, p2)
- n.Ninit = ll
- Patch(Gbranch(obj.AJMP, nil, 0), to)
- Patch(p2, Pc)
- return
- }
-
- a = Brcom(a)
- true_ = !true_
+ if !wantTrue {
+ if Isfloat[nr.Type.Etype] {
+ // Brcom is not valid on floats when NaN is involved.
+ p1 := Gbranch(obj.AJMP, nil, 0)
+ p2 := Gbranch(obj.AJMP, nil, 0)
+ Patch(p1, Pc)
+ ll := n.Ninit // avoid re-genning Ninit
+ n.Ninit = nil
+ Bgen(n, true, -likely, p2)
+ n.Ninit = ll
+ Patch(Gbranch(obj.AJMP, nil, 0), to)
+ Patch(p2, Pc)
+ return
}
- // make simplest on right
- if nl.Op == OLITERAL || (nl.Ullman < nr.Ullman && nl.Ullman < UINF) {
- a = Brrev(a)
- r := nl
- nl = nr
- nr = r
- }
+ a = Brcom(a)
+ }
+ wantTrue = true
- if Isslice(nl.Type) {
- // front end should only leave cmp to literal nil
- if (a != OEQ && a != ONE) || nr.Op != OLITERAL {
+ // make simplest on right
+ if nl.Op == OLITERAL || (nl.Ullman < nr.Ullman && nl.Ullman < UINF) {
+ a = Brrev(a)
+ nl, nr = nr, nl
+ }
+
+ if Isslice(nl.Type) || Isinter(nl.Type) {
+ // front end should only leave cmp to literal nil
+ if (a != OEQ && a != ONE) || nr.Op != OLITERAL {
+ if Isslice(nl.Type) {
Yyerror("illegal slice comparison")
- break
- }
-
- a = Thearch.Optoas(a, Types[Tptr])
- var n1 Node
- Igen(nl, &n1, nil)
- n1.Xoffset += int64(Array_array)
- n1.Type = Types[Tptr]
- var n2 Node
- Regalloc(&n2, Types[Tptr], &n1)
- Cgen(&n1, &n2)
- Regfree(&n1)
- var tmp Node
- Nodconst(&tmp, Types[Tptr], 0)
- Thearch.Gins(Thearch.Optoas(OCMP, Types[Tptr]), &n2, &tmp)
- Patch(Gbranch(a, Types[Tptr], likely), to)
- Regfree(&n2)
- break
- }
-
- if Isinter(nl.Type) {
- // front end should only leave cmp to literal nil
- if (a != OEQ && a != ONE) || nr.Op != OLITERAL {
+ } else {
Yyerror("illegal interface comparison")
- break
}
-
- a = Thearch.Optoas(a, Types[Tptr])
- var n1 Node
- Igen(nl, &n1, nil)
- n1.Type = Types[Tptr]
- var n2 Node
- Regalloc(&n2, Types[Tptr], &n1)
- Cgen(&n1, &n2)
- Regfree(&n1)
- var tmp Node
- Nodconst(&tmp, Types[Tptr], 0)
- Thearch.Gins(Thearch.Optoas(OCMP, Types[Tptr]), &n2, &tmp)
- Patch(Gbranch(a, Types[Tptr], likely), to)
- Regfree(&n2)
- break
+ return
}
- if Iscomplex[nl.Type.Etype] {
- Complexbool(a, nl, nr, true_, likely, to)
- break
+ var ptr Node
+ Igen(nl, &ptr, nil)
+ if Isslice(nl.Type) {
+ ptr.Xoffset += int64(Array_array)
}
+ ptr.Type = Types[Tptr]
+ var tmp Node
+ Regalloc(&tmp, ptr.Type, &ptr)
+ Cgen(&ptr, &tmp)
+ Regfree(&ptr)
+ bgenNonZero(&tmp, a == OEQ != wantTrue, likely, to)
+ Regfree(&tmp)
+ return
+ }
- if Ctxt.Arch.Regsize == 4 && Is64(nr.Type) {
- if !nl.Addable || Isconst(nl, CTINT) {
- var n1 Node
- Tempname(&n1, nl.Type)
- Cgen(nl, &n1)
- nl = &n1
- }
+ if Iscomplex[nl.Type.Etype] {
+ complexbool(a, nl, nr, wantTrue, likely, to)
+ return
+ }
- if !nr.Addable {
- var n2 Node
- Tempname(&n2, nr.Type)
- Cgen(nr, &n2)
- nr = &n2
- }
-
- Thearch.Cmp64(nl, nr, a, likely, to)
- break
+ if Ctxt.Arch.Regsize == 4 && Is64(nr.Type) {
+ if !nl.Addable || Isconst(nl, CTINT) {
+ nl = CgenTemp(nl)
}
+ if !nr.Addable {
+ nr = CgenTemp(nr)
+ }
+ Thearch.Cmp64(nl, nr, a, likely, to)
+ return
+ }
+ if nr.Ullman >= UINF {
var n1 Node
+ Regalloc(&n1, nl.Type, nil)
+ Cgen(nl, &n1)
+
+ var tmp Node
+ Tempname(&tmp, nl.Type)
+ Thearch.Gmove(&n1, &tmp)
+ Regfree(&n1)
+
var n2 Node
- if nr.Ullman >= UINF {
- Regalloc(&n1, nl.Type, nil)
- Cgen(nl, &n1)
+ Regalloc(&n2, nr.Type, nil)
+ Cgen(nr, &n2)
+ Regfree(&n2)
- var tmp Node
- Tempname(&tmp, nl.Type)
- Thearch.Gmove(&n1, &tmp)
- Regfree(&n1)
-
- Regalloc(&n2, nr.Type, nil)
- Cgen(nr, &n2)
-
- Regalloc(&n1, nl.Type, nil)
- Cgen(&tmp, &n1)
-
- goto cmp
- }
-
+ Regalloc(&n1, nl.Type, nil)
+ Cgen(&tmp, &n1)
+ Regfree(&n1)
+ } else {
+ var n1 Node
if !nl.Addable && Ctxt.Arch.Thechar == '8' {
Tempname(&n1, nl.Type)
} else {
Regalloc(&n1, nl.Type, nil)
+ defer Regfree(&n1)
}
Cgen(nl, &n1)
nl = &n1
@@ -1877,92 +1839,93 @@
if Smallintconst(nr) && Ctxt.Arch.Thechar != '9' {
Thearch.Gins(Thearch.Optoas(OCMP, nr.Type), nl, nr)
Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
- if n1.Op == OREGISTER {
- Regfree(&n1)
- }
- break
+ return
}
if !nr.Addable && Ctxt.Arch.Thechar == '8' {
- var tmp Node
- Tempname(&tmp, nr.Type)
- Cgen(nr, &tmp)
- nr = &tmp
+ nr = CgenTemp(nr)
}
+ var n2 Node
Regalloc(&n2, nr.Type, nil)
Cgen(nr, &n2)
nr = &n2
+ Regfree(&n2)
+ }
- cmp:
- l, r := nl, nr
- // On x86, only < and <= work right with NaN; reverse if needed
- if Ctxt.Arch.Thechar == '6' && Isfloat[nl.Type.Etype] && (a == OGT || a == OGE) {
- l, r = r, l
- a = Brrev(a)
- }
+ l, r := nl, nr
- Thearch.Gins(Thearch.Optoas(OCMP, nr.Type), l, r)
+ // On x86, only < and <= work right with NaN; reverse if needed
+ if Ctxt.Arch.Thechar == '6' && Isfloat[nl.Type.Etype] && (a == OGT || a == OGE) {
+ l, r = r, l
+ a = Brrev(a)
+ }
- if Ctxt.Arch.Thechar == '6' && Isfloat[nr.Type.Etype] && (n.Op == OEQ || n.Op == ONE) {
- if n.Op == OEQ {
+ // Do the comparison.
+ Thearch.Gins(Thearch.Optoas(OCMP, nr.Type), l, r)
+
+ // Handle floating point special cases.
+ // Note that 8g has Bgen_float and is handled above.
+ if Isfloat[nl.Type.Etype] {
+ switch Ctxt.Arch.Thechar {
+ case '5':
+ switch n.Op {
+ case ONE:
+ Patch(Gbranch(Thearch.Optoas(OPS, nr.Type), nr.Type, likely), to)
+ Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
+ default:
+ p := Gbranch(Thearch.Optoas(OPS, nr.Type), nr.Type, -likely)
+ Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
+ Patch(p, Pc)
+ }
+ return
+ case '6':
+ switch n.Op {
+ case OEQ:
// neither NE nor P
p1 := Gbranch(Thearch.Optoas(ONE, nr.Type), nil, -likely)
p2 := Gbranch(Thearch.Optoas(OPS, nr.Type), nil, -likely)
Patch(Gbranch(obj.AJMP, nil, 0), to)
Patch(p1, Pc)
Patch(p2, Pc)
- } else {
+ return
+ case ONE:
// either NE or P
Patch(Gbranch(Thearch.Optoas(ONE, nr.Type), nil, likely), to)
Patch(Gbranch(Thearch.Optoas(OPS, nr.Type), nil, likely), to)
+ return
}
- } else if Ctxt.Arch.Thechar == '5' && Isfloat[nl.Type.Etype] {
- if n.Op == ONE {
- Patch(Gbranch(Thearch.Optoas(OPS, nr.Type), nr.Type, likely), to)
- Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
- } else {
- p := Gbranch(Thearch.Optoas(OPS, nr.Type), nr.Type, -likely)
- Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
- Patch(p, Pc)
- }
- } else if (Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9') && Isfloat[nl.Type.Etype] && (a == OLE || a == OGE) {
+ case '7', '9':
+ switch n.Op {
// On arm64 and ppc64, <= and >= mishandle NaN. Must decompose into < or > and =.
- if a == OLE {
- a = OLT
- } else {
- a = OGT
+ // TODO(josh): Convert a <= b to b > a instead?
+ case OLE, OGE:
+ if a == OLE {
+ a = OLT
+ } else {
+ a = OGT
+ }
+ Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
+ Patch(Gbranch(Thearch.Optoas(OEQ, nr.Type), nr.Type, likely), to)
+ return
}
- Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
- Patch(Gbranch(Thearch.Optoas(OEQ, nr.Type), nr.Type, likely), to)
- } else {
- Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
- }
- if n1.Op == OREGISTER {
- Regfree(&n1)
- }
- if n2.Op == OREGISTER {
- Regfree(&n2)
}
}
- return
+ // Not a special case. Insert an appropriate conditional jump.
+ Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
+}
-def:
+func bgenNonZero(n *Node, wantTrue bool, likely int, to *obj.Prog) {
// TODO: Optimize on systems that can compare to zero easily.
- var n1 Node
- Regalloc(&n1, n.Type, nil)
- Cgen(n, &n1)
- var n2 Node
- Nodconst(&n2, n.Type, 0)
- Thearch.Gins(Thearch.Optoas(OCMP, n.Type), &n1, &n2)
- a := Thearch.Optoas(ONE, n.Type)
- if !true_ {
- a = Thearch.Optoas(OEQ, n.Type)
+ a := ONE
+ if !wantTrue {
+ a = OEQ
}
- Patch(Gbranch(a, n.Type, likely), to)
- Regfree(&n1)
- return
+ var zero Node
+ Nodconst(&zero, n.Type, 0)
+ Thearch.Gins(Thearch.Optoas(OCMP, n.Type), n, &zero)
+ Patch(Gbranch(Thearch.Optoas(a, n.Type), n.Type, likely), to)
}
/*
diff --git a/src/cmd/internal/gc/cplx.go b/src/cmd/internal/gc/cplx.go
index ec6984c..73251bd 100644
--- a/src/cmd/internal/gc/cplx.go
+++ b/src/cmd/internal/gc/cplx.go
@@ -6,10 +6,6 @@
import "cmd/internal/obj"
-func CASE(a int, b int) int {
- return a<<16 | b
-}
-
func overlap_cplx(f *Node, t *Node) bool {
// check whether f and t could be overlapping stack references.
// not exact, because it's hard to check for the stack register
@@ -18,67 +14,52 @@
return f.Op == OINDREG && t.Op == OINDREG && f.Xoffset+f.Type.Width >= t.Xoffset && t.Xoffset+t.Type.Width >= f.Xoffset
}
-func Complexbool(op int, nl *Node, nr *Node, true_ bool, likely int, to *obj.Prog) {
- var tnl Node
-
+func complexbool(op int, nl, nr *Node, wantTrue bool, likely int, to *obj.Prog) {
// make both sides addable in ullman order
if nr != nil {
if nl.Ullman > nr.Ullman && !nl.Addable {
- Tempname(&tnl, nl.Type)
- Cgen(nl, &tnl)
- nl = &tnl
+ nl = CgenTemp(nl)
}
if !nr.Addable {
- var tnr Node
- Tempname(&tnr, nr.Type)
- Cgen(nr, &tnr)
- nr = &tnr
+ nr = CgenTemp(nr)
}
}
-
if !nl.Addable {
- Tempname(&tnl, nl.Type)
- Cgen(nl, &tnl)
- nl = &tnl
+ nl = CgenTemp(nl)
}
+ // Break nl and nr into real and imaginary components.
+ var lreal, limag, rreal, rimag Node
+ subnode(&lreal, &limag, nl)
+ subnode(&rreal, &rimag, nr)
+
// build tree
// real(l) == real(r) && imag(l) == imag(r)
-
- var n2 Node
- var n1 Node
- subnode(&n1, &n2, nl)
-
- var n3 Node
- var n4 Node
- subnode(&n3, &n4, nr)
-
- var na Node
- na.Op = OANDAND
- var nb Node
- na.Left = &nb
- var nc Node
- na.Right = &nc
- na.Type = Types[TBOOL]
-
- nb = Node{}
- nb.Op = OEQ
- nb.Left = &n1
- nb.Right = &n3
- nb.Type = Types[TBOOL]
-
- nc = Node{}
- nc.Op = OEQ
- nc.Left = &n2
- nc.Right = &n4
- nc.Type = Types[TBOOL]
-
- if op == ONE {
- true_ = !true_
+ realeq := Node{
+ Op: OEQ,
+ Left: &lreal,
+ Right: &rreal,
+ Type: Types[TBOOL],
+ }
+ imageq := Node{
+ Op: OEQ,
+ Left: &limag,
+ Right: &rimag,
+ Type: Types[TBOOL],
+ }
+ and := Node{
+ Op: OANDAND,
+ Left: &realeq,
+ Right: &imageq,
+ Type: Types[TBOOL],
}
- Bgen(&na, true_, likely, to)
+ if op == ONE {
+ wantTrue = !wantTrue
+ }
+
+ Bgen(&and, wantTrue, likely, to)
}
// break addable nc-complex into nr-real and ni-imaginary
diff --git a/src/cmd/internal/gc/gen.go b/src/cmd/internal/gc/gen.go
index e95ddeb..60de083 100644
--- a/src/cmd/internal/gc/gen.go
+++ b/src/cmd/internal/gc/gen.go
@@ -1091,6 +1091,14 @@
cgen_call(&n2, proc)
}
+// CgenTemp creates a temporary node, assigns n to it, and returns it.
+func CgenTemp(n *Node) *Node {
+ var tmp Node
+ Tempname(&tmp, n.Type)
+ Cgen(n, &tmp)
+ return &tmp
+}
+
func checklabels() {
var l *NodeList
diff --git a/src/cmd/internal/gc/go.go b/src/cmd/internal/gc/go.go
index b63f4e8..c0ec7b5 100644
--- a/src/cmd/internal/gc/go.go
+++ b/src/cmd/internal/gc/go.go
@@ -776,8 +776,8 @@
AddIndex func(*Node, int64, *Node) bool // optional
Betypeinit func()
- Bgen_float func(*Node, int, int, *obj.Prog) // optional
- Cgen64 func(*Node, *Node) // only on 32-bit systems
+ Bgen_float func(*Node, bool, int, *obj.Prog) // optional
+ Cgen64 func(*Node, *Node) // only on 32-bit systems
Cgenindex func(*Node, *Node, bool) *obj.Prog
Cgen_bmul func(int, *Node, *Node, *Node) bool
Cgen_float func(*Node, *Node) // optional
diff --git a/src/cmd/internal/gc/subr.go b/src/cmd/internal/gc/subr.go
index c18f1e9..5b883d8 100644
--- a/src/cmd/internal/gc/subr.go
+++ b/src/cmd/internal/gc/subr.go
@@ -1796,10 +1796,8 @@
return *getinarg(t)
}
-/*
- * return !(op)
- * eg == <=> !=
- */
+// Brcom returns !(op).
+// For example, Brcom(==) is !=.
func Brcom(a int) int {
switch a {
case OEQ:
@@ -1815,15 +1813,12 @@
case OGE:
return OLT
}
-
- Fatal("brcom: no com for %v\n", Oconv(int(a), 0))
+ Fatal("brcom: no com for %v\n", Oconv(a, 0))
return a
}
-/*
- * return reverse(op)
- * eg a op b <=> b r(op) a
- */
+// Brrev returns reverse(op).
+// For example, Brrev(<) is >.
func Brrev(a int) int {
switch a {
case OEQ:
@@ -1839,8 +1834,7 @@
case OGE:
return OLE
}
-
- Fatal("brcom: no rev for %v\n", Oconv(int(a), 0))
+ Fatal("brrev: no rev for %v\n", Oconv(a, 0))
return a
}