Skip to content

Commit f12bd8a

Browse files
committed
cmd/compile: encapsulate OSLICE* representation
As a nice side-effect, this allows us to unify several code paths. The terminology (low, high, max, simple slice expr, full slice expr) is taken from the spec and the examples in the spec. This is a trial run. The plan, probably for Go 1.8, is to change slice expressions to use Node.List instead of OKEY, and to do some similar tree structure changes for other ops. Passes toolstash -cmp. No performance change. all.bash passes with GO_GCFLAGS=-newexport. Updates #15350 Change-Id: Ic1efdc36e79cdb95ae1636e9817a3ac8f83ab1ac Reviewed-on: https://go-review.googlesource.com/22425 Reviewed-by: Matthew Dempsky <[email protected]>
1 parent 2bf7034 commit f12bd8a

File tree

13 files changed

+205
-199
lines changed

13 files changed

+205
-199
lines changed

src/cmd/compile/internal/gc/bexport.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,12 +1191,15 @@ func (p *exporter) expr(n *Node) {
11911191
case OSLICE, OSLICESTR, OSLICEARR:
11921192
p.op(OSLICE)
11931193
p.expr(n.Left)
1194-
p.expr(n.Right)
1194+
low, high, _ := n.SliceBounds()
1195+
p.exprsOrNil(low, high)
11951196

11961197
case OSLICE3, OSLICE3ARR:
11971198
p.op(OSLICE3)
11981199
p.expr(n.Left)
1199-
p.expr(n.Right)
1200+
low, high, max := n.SliceBounds()
1201+
p.exprsOrNil(low, high)
1202+
p.expr(max)
12001203

12011204
case OCOPY, OCOMPLEX:
12021205
p.op(op)

src/cmd/compile/internal/gc/bimport.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -822,9 +822,19 @@ func (p *importer) node() *Node {
822822
// case OINDEX, OINDEXMAP, OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR:
823823
// unreachable - mapped to cases below by exporter
824824

825-
case OINDEX, OSLICE, OSLICE3:
825+
case OINDEX:
826826
return Nod(op, p.expr(), p.expr())
827827

828+
case OSLICE, OSLICE3:
829+
n := Nod(op, p.expr(), nil)
830+
low, high := p.exprsOrNil()
831+
var max *Node
832+
if n.Op.IsSlice3() {
833+
max = p.expr()
834+
}
835+
n.SetSliceBounds(low, high, max)
836+
return n
837+
828838
case OCOPY, OCOMPLEX:
829839
n := builtinCall(op)
830840
n.List.Set([]*Node{p.expr(), p.expr()})

src/cmd/compile/internal/gc/cgen.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3106,15 +3106,7 @@ func cgen_slice(n, res *Node, wb bool) {
31063106
x.Xoffset -= 2 * int64(Widthptr)
31073107
}
31083108

3109-
var x1, x2, x3 *Node // unevaluated index arguments
3110-
x1 = n.Right.Left
3111-
switch n.Op {
3112-
default:
3113-
x2 = n.Right.Right
3114-
case OSLICE3, OSLICE3ARR:
3115-
x2 = n.Right.Right.Left
3116-
x3 = n.Right.Right.Right
3117-
}
3109+
x1, x2, x3 := n.SliceBounds() // unevaluated index arguments
31183110

31193111
// load computes src into targ, but if src refers to the len or cap of n.Left,
31203112
// load copies those from xlen, xcap, loading xlen if needed.

src/cmd/compile/internal/gc/fmt.go

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,17 +1312,29 @@ func exprfmt(n *Node, prec int) string {
13121312
f += fmt.Sprintf(".(%v)", n.Type)
13131313
return f
13141314

1315-
case OINDEX,
1316-
OINDEXMAP,
1317-
OSLICE,
1318-
OSLICESTR,
1319-
OSLICEARR,
1320-
OSLICE3,
1321-
OSLICE3ARR:
1322-
var f string
1323-
f += exprfmt(n.Left, nprec)
1324-
f += fmt.Sprintf("[%v]", n.Right)
1325-
return f
1315+
case OINDEX, OINDEXMAP:
1316+
return fmt.Sprintf("%s[%v]", exprfmt(n.Left, nprec), n.Right)
1317+
1318+
case OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR:
1319+
var buf bytes.Buffer
1320+
buf.WriteString(exprfmt(n.Left, nprec))
1321+
buf.WriteString("[")
1322+
low, high, max := n.SliceBounds()
1323+
if low != nil {
1324+
buf.WriteString(low.String())
1325+
}
1326+
buf.WriteString(":")
1327+
if high != nil {
1328+
buf.WriteString(high.String())
1329+
}
1330+
if n.Op.IsSlice3() {
1331+
buf.WriteString(":")
1332+
if max != nil {
1333+
buf.WriteString(max.String())
1334+
}
1335+
}
1336+
buf.WriteString("]")
1337+
return buf.String()
13261338

13271339
case OCOPY, OCOMPLEX:
13281340
return fmt.Sprintf("%v(%v, %v)", Oconv(n.Op, FmtSharp), n.Left, n.Right)

src/cmd/compile/internal/gc/inl.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,7 @@ func mkinlcall1(n *Node, fn *Node, isddd bool) *Node {
754754
vararrtype := typArray(varargtype.Elem(), int64(varargcount))
755755
as.Right = Nod(OCOMPLIT, nil, typenod(vararrtype))
756756
as.Right.List.Set(varargs)
757-
as.Right = Nod(OSLICE, as.Right, Nod(OKEY, nil, nil))
757+
as.Right = Nod(OSLICE, as.Right, nil)
758758
}
759759

760760
as = typecheck(as, Etop)

src/cmd/compile/internal/gc/order.go

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,24 +1123,16 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node {
11231123
n = ordercopyexpr(n, n.Type, order, 0)
11241124
}
11251125

1126-
case OSLICE, OSLICEARR, OSLICESTR:
1126+
case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
11271127
n.Left = orderexpr(n.Left, order, nil)
1128-
n.Right.Left = orderexpr(n.Right.Left, order, nil)
1129-
n.Right.Left = ordercheapexpr(n.Right.Left, order)
1130-
n.Right.Right = orderexpr(n.Right.Right, order, nil)
1131-
n.Right.Right = ordercheapexpr(n.Right.Right, order)
1132-
if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
1133-
n = ordercopyexpr(n, n.Type, order, 0)
1134-
}
1135-
1136-
case OSLICE3, OSLICE3ARR:
1137-
n.Left = orderexpr(n.Left, order, nil)
1138-
n.Right.Left = orderexpr(n.Right.Left, order, nil)
1139-
n.Right.Left = ordercheapexpr(n.Right.Left, order)
1140-
n.Right.Right.Left = orderexpr(n.Right.Right.Left, order, nil)
1141-
n.Right.Right.Left = ordercheapexpr(n.Right.Right.Left, order)
1142-
n.Right.Right.Right = orderexpr(n.Right.Right.Right, order, nil)
1143-
n.Right.Right.Right = ordercheapexpr(n.Right.Right.Right, order)
1128+
low, high, max := n.SliceBounds()
1129+
low = orderexpr(low, order, nil)
1130+
low = ordercheapexpr(low, order)
1131+
high = orderexpr(high, order, nil)
1132+
high = ordercheapexpr(high, order)
1133+
max = orderexpr(max, order, nil)
1134+
max = ordercheapexpr(max, order)
1135+
n.SetSliceBounds(low, high, max)
11441136
if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
11451137
n = ordercopyexpr(n, n.Type, order, 0)
11461138
}

src/cmd/compile/internal/gc/parser.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,20 +1408,17 @@ loop:
14081408
}
14091409
x = Nod(OINDEX, x, i)
14101410
case 1:
1411-
i := index[0]
1412-
j := index[1]
1413-
x = Nod(OSLICE, x, Nod(OKEY, i, j))
1411+
x = Nod(OSLICE, x, nil)
1412+
x.SetSliceBounds(index[0], index[1], nil)
14141413
case 2:
1415-
i := index[0]
1416-
j := index[1]
1417-
k := index[2]
1418-
if j == nil {
1414+
if index[1] == nil {
14191415
Yyerror("middle index required in 3-index slice")
14201416
}
1421-
if k == nil {
1417+
if index[2] == nil {
14221418
Yyerror("final index required in 3-index slice")
14231419
}
1424-
x = Nod(OSLICE3, x, Nod(OKEY, i, Nod(OKEY, j, k)))
1420+
x = Nod(OSLICE3, x, nil)
1421+
x.SetSliceBounds(index[0], index[1], index[2])
14251422

14261423
default:
14271424
panic("unreachable")

src/cmd/compile/internal/gc/racewalk.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,11 @@ func instrumentnode(np **Node, init *Nodes, wr int, skip int) {
307307

308308
case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR, OSLICESTR:
309309
instrumentnode(&n.Left, init, 0, 0)
310-
instrumentnode(&n.Right, init, 0, 0)
310+
low, high, max := n.SliceBounds()
311+
instrumentnode(&low, init, 0, 0)
312+
instrumentnode(&high, init, 0, 0)
313+
instrumentnode(&max, init, 0, 0)
314+
n.SetSliceBounds(low, high, max)
311315
goto ret
312316

313317
case OKEY:

src/cmd/compile/internal/gc/sinit.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
727727
arraylit(ctxt, 2, n, vstat, init)
728728

729729
// copy static to slice
730-
a := Nod(OSLICE, vstat, Nod(OKEY, nil, nil))
730+
a := Nod(OSLICE, vstat, nil)
731731

732732
a = Nod(OAS, var_, a)
733733
a = typecheck(a, Etop)
@@ -851,7 +851,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
851851
}
852852

853853
// make slice out of heap (6)
854-
a = Nod(OAS, var_, Nod(OSLICE, vauto, Nod(OKEY, nil, nil)))
854+
a = Nod(OAS, var_, Nod(OSLICE, vauto, nil))
855855

856856
a = typecheck(a, Etop)
857857
a = orderstmtinplace(a)
@@ -1391,7 +1391,8 @@ func genAsInitNoCheck(n *Node, reportOnly bool) bool {
13911391
fallthrough
13921392

13931393
case OSLICEARR:
1394-
if nr.Right.Op != OKEY || nr.Right.Left != nil || nr.Right.Right != nil {
1394+
low, high, _ := nr.SliceBounds()
1395+
if low != nil || high != nil {
13951396
return false
13961397
}
13971398
nr = nr.Left

src/cmd/compile/internal/gc/ssa.go

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -736,14 +736,7 @@ func (s *state) stmt(n *Node) {
736736
if rhs != nil && (rhs.Op == OSLICE || rhs.Op == OSLICE3 || rhs.Op == OSLICESTR) && samesafeexpr(rhs.Left, n.Left) {
737737
// We're assigning a slicing operation back to its source.
738738
// Don't write back fields we aren't changing. See issue #14855.
739-
i := rhs.Right.Left
740-
var j, k *Node
741-
if rhs.Op == OSLICE3 {
742-
j = rhs.Right.Right.Left
743-
k = rhs.Right.Right.Right
744-
} else {
745-
j = rhs.Right.Right
746-
}
739+
i, j, k := rhs.SliceBounds()
747740
if i != nil && (i.Op == OLITERAL && i.Val().Ctype() == CTINT && i.Int64() == 0) {
748741
// [0:...] is the same as [:...]
749742
i = nil
@@ -2038,38 +2031,34 @@ func (s *state) expr(n *Node) *ssa.Value {
20382031
}
20392032
return s.newValue2(ssa.OpIMake, n.Type, tab, data)
20402033

2041-
case OSLICE, OSLICEARR:
2034+
case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR:
20422035
v := s.expr(n.Left)
2043-
var i, j *ssa.Value
2044-
if n.Right.Left != nil {
2045-
i = s.extendIndex(s.expr(n.Right.Left))
2036+
var i, j, k *ssa.Value
2037+
low, high, max := n.SliceBounds()
2038+
if low != nil {
2039+
i = s.extendIndex(s.expr(low))
20462040
}
2047-
if n.Right.Right != nil {
2048-
j = s.extendIndex(s.expr(n.Right.Right))
2041+
if high != nil {
2042+
j = s.extendIndex(s.expr(high))
20492043
}
2050-
p, l, c := s.slice(n.Left.Type, v, i, j, nil)
2044+
if max != nil {
2045+
k = s.extendIndex(s.expr(max))
2046+
}
2047+
p, l, c := s.slice(n.Left.Type, v, i, j, k)
20512048
return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c)
2049+
20522050
case OSLICESTR:
20532051
v := s.expr(n.Left)
20542052
var i, j *ssa.Value
2055-
if n.Right.Left != nil {
2056-
i = s.extendIndex(s.expr(n.Right.Left))
2053+
low, high, _ := n.SliceBounds()
2054+
if low != nil {
2055+
i = s.extendIndex(s.expr(low))
20572056
}
2058-
if n.Right.Right != nil {
2059-
j = s.extendIndex(s.expr(n.Right.Right))
2057+
if high != nil {
2058+
j = s.extendIndex(s.expr(high))
20602059
}
20612060
p, l, _ := s.slice(n.Left.Type, v, i, j, nil)
20622061
return s.newValue2(ssa.OpStringMake, n.Type, p, l)
2063-
case OSLICE3, OSLICE3ARR:
2064-
v := s.expr(n.Left)
2065-
var i *ssa.Value
2066-
if n.Right.Left != nil {
2067-
i = s.extendIndex(s.expr(n.Right.Left))
2068-
}
2069-
j := s.extendIndex(s.expr(n.Right.Right.Left))
2070-
k := s.extendIndex(s.expr(n.Right.Right.Right))
2071-
p, l, c := s.slice(n.Left.Type, v, i, j, k)
2072-
return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c)
20732062

20742063
case OCALLFUNC:
20752064
if isIntrinsicCall1(n) {

src/cmd/compile/internal/gc/subr.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,68 @@ func Is64(t *Type) bool {
10241024
return false
10251025
}
10261026

1027+
// SliceBounds returns n's slice bounds: low, high, and max in expr[low:high:max].
1028+
// n must be a slice expression. max is nil if n is a simple slice expression.
1029+
func (n *Node) SliceBounds() (low, high, max *Node) {
1030+
switch n.Op {
1031+
case OSLICE, OSLICEARR, OSLICESTR:
1032+
if n.Right == nil {
1033+
return nil, nil, nil
1034+
}
1035+
if n.Right.Op != OKEY {
1036+
Fatalf("SliceBounds right %s", opnames[n.Right.Op])
1037+
}
1038+
return n.Right.Left, n.Right.Right, nil
1039+
case OSLICE3, OSLICE3ARR:
1040+
if n.Right.Op != OKEY || n.Right.Right.Op != OKEY {
1041+
Fatalf("SliceBounds right %s %s", opnames[n.Right.Op], opnames[n.Right.Right.Op])
1042+
}
1043+
return n.Right.Left, n.Right.Right.Left, n.Right.Right.Right
1044+
}
1045+
Fatalf("SliceBounds op %s: %v", n.Op, n)
1046+
return nil, nil, nil
1047+
}
1048+
1049+
// SetSliceBounds sets n's slice bounds, where n is a slice expression.
1050+
// n must be a slice expression. If max is non-nil, n must be a full slice expression.
1051+
func (n *Node) SetSliceBounds(low, high, max *Node) {
1052+
switch n.Op {
1053+
case OSLICE, OSLICEARR, OSLICESTR:
1054+
if max != nil {
1055+
Fatalf("SetSliceBounds %s given three bounds", n.Op)
1056+
}
1057+
if n.Right == nil {
1058+
n.Right = Nod(OKEY, low, high)
1059+
return
1060+
}
1061+
n.Right.Left = low
1062+
n.Right.Right = high
1063+
return
1064+
case OSLICE3, OSLICE3ARR:
1065+
if n.Right == nil {
1066+
n.Right = Nod(OKEY, low, Nod(OKEY, high, max))
1067+
}
1068+
n.Right.Left = low
1069+
n.Right.Right.Left = high
1070+
n.Right.Right.Right = max
1071+
return
1072+
}
1073+
Fatalf("SetSliceBounds op %s: %v", n.Op, n)
1074+
}
1075+
1076+
// IsSlice3 reports whether o is a slice3 op (OSLICE3, OSLICE3ARR).
1077+
// o must be a slicing op.
1078+
func (o Op) IsSlice3() bool {
1079+
switch o {
1080+
case OSLICE, OSLICEARR, OSLICESTR:
1081+
return false
1082+
case OSLICE3, OSLICE3ARR:
1083+
return true
1084+
}
1085+
Fatalf("IsSlice3 op %v", o)
1086+
return false
1087+
}
1088+
10271089
// Is a conversion between t1 and t2 a no-op?
10281090
func Noconv(t1 *Type, t2 *Type) bool {
10291091
e1 := Simtype[t1.Etype]

0 commit comments

Comments
 (0)