diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go index f0907b45eb..bf1354c71f 100644 --- a/src/cmd/compile/internal/gc/bexport.go +++ b/src/cmd/compile/internal/gc/bexport.go @@ -1191,12 +1191,15 @@ func (p *exporter) expr(n *Node) { case OSLICE, OSLICESTR, OSLICEARR: p.op(OSLICE) p.expr(n.Left) - p.expr(n.Right) + low, high, _ := n.SliceBounds() + p.exprsOrNil(low, high) case OSLICE3, OSLICE3ARR: p.op(OSLICE3) p.expr(n.Left) - p.expr(n.Right) + low, high, max := n.SliceBounds() + p.exprsOrNil(low, high) + p.expr(max) case OCOPY, OCOMPLEX: p.op(op) diff --git a/src/cmd/compile/internal/gc/bimport.go b/src/cmd/compile/internal/gc/bimport.go index 1219d8d370..3665bbdec2 100644 --- a/src/cmd/compile/internal/gc/bimport.go +++ b/src/cmd/compile/internal/gc/bimport.go @@ -822,9 +822,19 @@ func (p *importer) node() *Node { // case OINDEX, OINDEXMAP, OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR: // unreachable - mapped to cases below by exporter - case OINDEX, OSLICE, OSLICE3: + case OINDEX: return Nod(op, p.expr(), p.expr()) + case OSLICE, OSLICE3: + n := Nod(op, p.expr(), nil) + low, high := p.exprsOrNil() + var max *Node + if n.Op.IsSlice3() { + max = p.expr() + } + n.SetSliceBounds(low, high, max) + return n + case OCOPY, OCOMPLEX: n := builtinCall(op) n.List.Set([]*Node{p.expr(), p.expr()}) diff --git a/src/cmd/compile/internal/gc/cgen.go b/src/cmd/compile/internal/gc/cgen.go index a9393a6d9e..3d3600a079 100644 --- a/src/cmd/compile/internal/gc/cgen.go +++ b/src/cmd/compile/internal/gc/cgen.go @@ -3106,15 +3106,7 @@ func cgen_slice(n, res *Node, wb bool) { x.Xoffset -= 2 * int64(Widthptr) } - var x1, x2, x3 *Node // unevaluated index arguments - x1 = n.Right.Left - switch n.Op { - default: - x2 = n.Right.Right - case OSLICE3, OSLICE3ARR: - x2 = n.Right.Right.Left - x3 = n.Right.Right.Right - } + x1, x2, x3 := n.SliceBounds() // unevaluated index arguments // load computes src into targ, but if src refers to the len or cap of n.Left, // load copies those from xlen, xcap, loading xlen if needed. diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go index 12ae915fb2..27ece1d393 100644 --- a/src/cmd/compile/internal/gc/fmt.go +++ b/src/cmd/compile/internal/gc/fmt.go @@ -1312,17 +1312,29 @@ func exprfmt(n *Node, prec int) string { f += fmt.Sprintf(".(%v)", n.Type) return f - case OINDEX, - OINDEXMAP, - OSLICE, - OSLICESTR, - OSLICEARR, - OSLICE3, - OSLICE3ARR: - var f string - f += exprfmt(n.Left, nprec) - f += fmt.Sprintf("[%v]", n.Right) - return f + case OINDEX, OINDEXMAP: + return fmt.Sprintf("%s[%v]", exprfmt(n.Left, nprec), n.Right) + + case OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR: + var buf bytes.Buffer + buf.WriteString(exprfmt(n.Left, nprec)) + buf.WriteString("[") + low, high, max := n.SliceBounds() + if low != nil { + buf.WriteString(low.String()) + } + buf.WriteString(":") + if high != nil { + buf.WriteString(high.String()) + } + if n.Op.IsSlice3() { + buf.WriteString(":") + if max != nil { + buf.WriteString(max.String()) + } + } + buf.WriteString("]") + return buf.String() case OCOPY, OCOMPLEX: return fmt.Sprintf("%v(%v, %v)", Oconv(n.Op, FmtSharp), n.Left, n.Right) diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index c863b84203..10b61377ca 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -754,7 +754,7 @@ func mkinlcall1(n *Node, fn *Node, isddd bool) *Node { vararrtype := typArray(varargtype.Elem(), int64(varargcount)) as.Right = Nod(OCOMPLIT, nil, typenod(vararrtype)) as.Right.List.Set(varargs) - as.Right = Nod(OSLICE, as.Right, Nod(OKEY, nil, nil)) + as.Right = Nod(OSLICE, as.Right, nil) } as = typecheck(as, Etop) diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index 00ba4308cb..7373479ac9 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -1123,24 +1123,16 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node { n = ordercopyexpr(n, n.Type, order, 0) } - case OSLICE, OSLICEARR, OSLICESTR: + case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR: n.Left = orderexpr(n.Left, order, nil) - n.Right.Left = orderexpr(n.Right.Left, order, nil) - n.Right.Left = ordercheapexpr(n.Right.Left, order) - n.Right.Right = orderexpr(n.Right.Right, order, nil) - n.Right.Right = ordercheapexpr(n.Right.Right, order) - if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) { - n = ordercopyexpr(n, n.Type, order, 0) - } - - case OSLICE3, OSLICE3ARR: - n.Left = orderexpr(n.Left, order, nil) - n.Right.Left = orderexpr(n.Right.Left, order, nil) - n.Right.Left = ordercheapexpr(n.Right.Left, order) - n.Right.Right.Left = orderexpr(n.Right.Right.Left, order, nil) - n.Right.Right.Left = ordercheapexpr(n.Right.Right.Left, order) - n.Right.Right.Right = orderexpr(n.Right.Right.Right, order, nil) - n.Right.Right.Right = ordercheapexpr(n.Right.Right.Right, order) + low, high, max := n.SliceBounds() + low = orderexpr(low, order, nil) + low = ordercheapexpr(low, order) + high = orderexpr(high, order, nil) + high = ordercheapexpr(high, order) + max = orderexpr(max, order, nil) + max = ordercheapexpr(max, order) + n.SetSliceBounds(low, high, max) if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) { n = ordercopyexpr(n, n.Type, order, 0) } diff --git a/src/cmd/compile/internal/gc/parser.go b/src/cmd/compile/internal/gc/parser.go index 766f352d33..97a18497ff 100644 --- a/src/cmd/compile/internal/gc/parser.go +++ b/src/cmd/compile/internal/gc/parser.go @@ -1408,20 +1408,17 @@ loop: } x = Nod(OINDEX, x, i) case 1: - i := index[0] - j := index[1] - x = Nod(OSLICE, x, Nod(OKEY, i, j)) + x = Nod(OSLICE, x, nil) + x.SetSliceBounds(index[0], index[1], nil) case 2: - i := index[0] - j := index[1] - k := index[2] - if j == nil { + if index[1] == nil { Yyerror("middle index required in 3-index slice") } - if k == nil { + if index[2] == nil { Yyerror("final index required in 3-index slice") } - x = Nod(OSLICE3, x, Nod(OKEY, i, Nod(OKEY, j, k))) + x = Nod(OSLICE3, x, nil) + x.SetSliceBounds(index[0], index[1], index[2]) default: panic("unreachable") diff --git a/src/cmd/compile/internal/gc/racewalk.go b/src/cmd/compile/internal/gc/racewalk.go index a8a5e92485..620bcb34a3 100644 --- a/src/cmd/compile/internal/gc/racewalk.go +++ b/src/cmd/compile/internal/gc/racewalk.go @@ -307,7 +307,11 @@ func instrumentnode(np **Node, init *Nodes, wr int, skip int) { case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR, OSLICESTR: instrumentnode(&n.Left, init, 0, 0) - instrumentnode(&n.Right, init, 0, 0) + low, high, max := n.SliceBounds() + instrumentnode(&low, init, 0, 0) + instrumentnode(&high, init, 0, 0) + instrumentnode(&max, init, 0, 0) + n.SetSliceBounds(low, high, max) goto ret case OKEY: diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go index cb43855514..c6f2acffbf 100644 --- a/src/cmd/compile/internal/gc/sinit.go +++ b/src/cmd/compile/internal/gc/sinit.go @@ -727,7 +727,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) { arraylit(ctxt, 2, n, vstat, init) // copy static to slice - a := Nod(OSLICE, vstat, Nod(OKEY, nil, nil)) + a := Nod(OSLICE, vstat, nil) a = Nod(OAS, var_, a) a = typecheck(a, Etop) @@ -851,7 +851,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) { } // make slice out of heap (6) - a = Nod(OAS, var_, Nod(OSLICE, vauto, Nod(OKEY, nil, nil))) + a = Nod(OAS, var_, Nod(OSLICE, vauto, nil)) a = typecheck(a, Etop) a = orderstmtinplace(a) @@ -1391,7 +1391,8 @@ func genAsInitNoCheck(n *Node, reportOnly bool) bool { fallthrough case OSLICEARR: - if nr.Right.Op != OKEY || nr.Right.Left != nil || nr.Right.Right != nil { + low, high, _ := nr.SliceBounds() + if low != nil || high != nil { return false } nr = nr.Left diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index e177ceda01..5c367c7268 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -736,14 +736,7 @@ func (s *state) stmt(n *Node) { if rhs != nil && (rhs.Op == OSLICE || rhs.Op == OSLICE3 || rhs.Op == OSLICESTR) && samesafeexpr(rhs.Left, n.Left) { // We're assigning a slicing operation back to its source. // Don't write back fields we aren't changing. See issue #14855. - i := rhs.Right.Left - var j, k *Node - if rhs.Op == OSLICE3 { - j = rhs.Right.Right.Left - k = rhs.Right.Right.Right - } else { - j = rhs.Right.Right - } + i, j, k := rhs.SliceBounds() if i != nil && (i.Op == OLITERAL && i.Val().Ctype() == CTINT && i.Int64() == 0) { // [0:...] is the same as [:...] i = nil @@ -2038,38 +2031,34 @@ func (s *state) expr(n *Node) *ssa.Value { } return s.newValue2(ssa.OpIMake, n.Type, tab, data) - case OSLICE, OSLICEARR: + case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR: v := s.expr(n.Left) - var i, j *ssa.Value - if n.Right.Left != nil { - i = s.extendIndex(s.expr(n.Right.Left)) + var i, j, k *ssa.Value + low, high, max := n.SliceBounds() + if low != nil { + i = s.extendIndex(s.expr(low)) } - if n.Right.Right != nil { - j = s.extendIndex(s.expr(n.Right.Right)) + if high != nil { + j = s.extendIndex(s.expr(high)) } - p, l, c := s.slice(n.Left.Type, v, i, j, nil) + if max != nil { + k = s.extendIndex(s.expr(max)) + } + p, l, c := s.slice(n.Left.Type, v, i, j, k) return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c) + case OSLICESTR: v := s.expr(n.Left) var i, j *ssa.Value - if n.Right.Left != nil { - i = s.extendIndex(s.expr(n.Right.Left)) + low, high, _ := n.SliceBounds() + if low != nil { + i = s.extendIndex(s.expr(low)) } - if n.Right.Right != nil { - j = s.extendIndex(s.expr(n.Right.Right)) + if high != nil { + j = s.extendIndex(s.expr(high)) } p, l, _ := s.slice(n.Left.Type, v, i, j, nil) return s.newValue2(ssa.OpStringMake, n.Type, p, l) - case OSLICE3, OSLICE3ARR: - v := s.expr(n.Left) - var i *ssa.Value - if n.Right.Left != nil { - i = s.extendIndex(s.expr(n.Right.Left)) - } - j := s.extendIndex(s.expr(n.Right.Right.Left)) - k := s.extendIndex(s.expr(n.Right.Right.Right)) - p, l, c := s.slice(n.Left.Type, v, i, j, k) - return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c) case OCALLFUNC: if isIntrinsicCall1(n) { diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 5fc16858d9..38f21eb585 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -1024,6 +1024,68 @@ func Is64(t *Type) bool { return false } +// SliceBounds returns n's slice bounds: low, high, and max in expr[low:high:max]. +// n must be a slice expression. max is nil if n is a simple slice expression. +func (n *Node) SliceBounds() (low, high, max *Node) { + switch n.Op { + case OSLICE, OSLICEARR, OSLICESTR: + if n.Right == nil { + return nil, nil, nil + } + if n.Right.Op != OKEY { + Fatalf("SliceBounds right %s", opnames[n.Right.Op]) + } + return n.Right.Left, n.Right.Right, nil + case OSLICE3, OSLICE3ARR: + if n.Right.Op != OKEY || n.Right.Right.Op != OKEY { + Fatalf("SliceBounds right %s %s", opnames[n.Right.Op], opnames[n.Right.Right.Op]) + } + return n.Right.Left, n.Right.Right.Left, n.Right.Right.Right + } + Fatalf("SliceBounds op %s: %v", n.Op, n) + return nil, nil, nil +} + +// SetSliceBounds sets n's slice bounds, where n is a slice expression. +// n must be a slice expression. If max is non-nil, n must be a full slice expression. +func (n *Node) SetSliceBounds(low, high, max *Node) { + switch n.Op { + case OSLICE, OSLICEARR, OSLICESTR: + if max != nil { + Fatalf("SetSliceBounds %s given three bounds", n.Op) + } + if n.Right == nil { + n.Right = Nod(OKEY, low, high) + return + } + n.Right.Left = low + n.Right.Right = high + return + case OSLICE3, OSLICE3ARR: + if n.Right == nil { + n.Right = Nod(OKEY, low, Nod(OKEY, high, max)) + } + n.Right.Left = low + n.Right.Right.Left = high + n.Right.Right.Right = max + return + } + Fatalf("SetSliceBounds op %s: %v", n.Op, n) +} + +// IsSlice3 reports whether o is a slice3 op (OSLICE3, OSLICE3ARR). +// o must be a slicing op. +func (o Op) IsSlice3() bool { + switch o { + case OSLICE, OSLICEARR, OSLICESTR: + return false + case OSLICE3, OSLICE3ARR: + return true + } + Fatalf("IsSlice3 op %v", o) + return false +} + // Is a conversion between t1 and t2 a no-op? func Noconv(t1 *Type, t2 *Type) bool { e1 := Simtype[t1.Etype] diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 49b991c5a5..8860c5d803 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -1105,14 +1105,19 @@ OpSwitch: n.Type = nil break OpSwitch - case OSLICE: + case OSLICE, OSLICE3: ok |= Erv n.Left = typecheck(n.Left, top) - n.Right.Left = typecheck(n.Right.Left, Erv) - n.Right.Right = typecheck(n.Right.Right, Erv) + low, high, max := n.SliceBounds() + hasmax := n.Op.IsSlice3() + low = typecheck(low, Erv) + high = typecheck(high, Erv) + max = typecheck(max, Erv) n.Left = defaultlit(n.Left, nil) - n.Right.Left = indexlit(n.Right.Left) - n.Right.Right = indexlit(n.Right.Right) + low = indexlit(low) + high = indexlit(high) + max = indexlit(max) + n.SetSliceBounds(low, high, max) l := n.Left if l.Type.IsArray() { if !islvalue(n.Left) { @@ -1134,78 +1139,22 @@ OpSwitch: } var tp *Type if t.IsString() { + if hasmax { + Yyerror("invalid operation %v (3-index slice of string)", n) + n.Type = nil + return n + } n.Type = t n.Op = OSLICESTR } else if t.IsPtr() && t.Elem().IsArray() { tp = t.Elem() n.Type = typSlice(tp.Elem()) dowidth(n.Type) - n.Op = OSLICEARR - } else if t.IsSlice() { - n.Type = t - } else { - Yyerror("cannot slice %v (type %v)", l, t) - n.Type = nil - return n - } - - lo := n.Right.Left - if lo != nil && !checksliceindex(l, lo, tp) { - n.Type = nil - return n - } - hi := n.Right.Right - if hi != nil && !checksliceindex(l, hi, tp) { - n.Type = nil - return n - } - if !checksliceconst(lo, hi) { - n.Type = nil - return n - } - break OpSwitch - - case OSLICE3: - ok |= Erv - n.Left = typecheck(n.Left, top) - n.Right.Left = typecheck(n.Right.Left, Erv) - n.Right.Right.Left = typecheck(n.Right.Right.Left, Erv) - n.Right.Right.Right = typecheck(n.Right.Right.Right, Erv) - n.Left = defaultlit(n.Left, nil) - n.Right.Left = indexlit(n.Right.Left) - n.Right.Right.Left = indexlit(n.Right.Right.Left) - n.Right.Right.Right = indexlit(n.Right.Right.Right) - l := n.Left - if l.Type.IsArray() { - if !islvalue(n.Left) { - Yyerror("invalid operation %v (slice of unaddressable value)", n) - n.Type = nil - return n + if hasmax { + n.Op = OSLICE3ARR + } else { + n.Op = OSLICEARR } - - n.Left = Nod(OADDR, n.Left, nil) - n.Left.Implicit = true - n.Left = typecheck(n.Left, Erv) - l = n.Left - } - - t := l.Type - if t == nil { - n.Type = nil - return n - } - if t.IsString() { - Yyerror("invalid operation %v (3-index slice of string)", n) - n.Type = nil - return n - } - - var tp *Type - if t.IsPtr() && t.Elem().IsArray() { - tp = t.Elem() - n.Type = typSlice(tp.Elem()) - dowidth(n.Type) - n.Op = OSLICE3ARR } else if t.IsSlice() { n.Type = t } else { @@ -1214,22 +1163,19 @@ OpSwitch: return n } - lo := n.Right.Left - if lo != nil && !checksliceindex(l, lo, tp) { + if low != nil && !checksliceindex(l, low, tp) { n.Type = nil return n } - mid := n.Right.Right.Left - if mid != nil && !checksliceindex(l, mid, tp) { + if high != nil && !checksliceindex(l, high, tp) { n.Type = nil return n } - hi := n.Right.Right.Right - if hi != nil && !checksliceindex(l, hi, tp) { + if max != nil && !checksliceindex(l, max, tp) { n.Type = nil return n } - if !checksliceconst(lo, hi) || !checksliceconst(lo, mid) || !checksliceconst(mid, hi) { + if !checksliceconst(low, high) || !checksliceconst(low, max) || !checksliceconst(high, max) { n.Type = nil return n } diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 04ccfad971..e8fee67d05 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -1241,35 +1241,28 @@ opswitch: case ORECV: Fatalf("walkexpr ORECV") // should see inside OAS only - case OSLICE, OSLICEARR, OSLICESTR: + case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR: n.Left = walkexpr(n.Left, init) - n.Right.Left = walkexpr(n.Right.Left, init) - if n.Right.Left != nil && iszero(n.Right.Left) { - // Reduce x[0:j] to x[:j]. - n.Right.Left = nil + low, high, max := n.SliceBounds() + low = walkexpr(low, init) + if low != nil && iszero(low) { + // Reduce x[0:j] to x[:j] and x[0:j:k] to x[:j:k]. + low = nil } - n.Right.Right = walkexpr(n.Right.Right, init) - n = reduceSlice(n) - - case OSLICE3, OSLICE3ARR: - n.Left = walkexpr(n.Left, init) - n.Right.Left = walkexpr(n.Right.Left, init) - if n.Right.Left != nil && iszero(n.Right.Left) { - // Reduce x[0:j:k] to x[:j:k]. - n.Right.Left = nil - } - n.Right.Right.Left = walkexpr(n.Right.Right.Left, init) - n.Right.Right.Right = walkexpr(n.Right.Right.Right, init) - - r := n.Right.Right.Right - if r != nil && r.Op == OCAP && samesafeexpr(n.Left, r.Left) { - // Reduce x[i:j:cap(x)] to x[i:j]. - n.Right.Right = n.Right.Right.Left - if n.Op == OSLICE3 { - n.Op = OSLICE - } else { - n.Op = OSLICEARR + high = walkexpr(high, init) + max = walkexpr(max, init) + n.SetSliceBounds(low, high, max) + if n.Op.IsSlice3() { + if max != nil && max.Op == OCAP && samesafeexpr(n.Left, max.Left) { + // Reduce x[i:j:cap(x)] to x[i:j]. + if n.Op == OSLICE3 { + n.Op = OSLICE + } else { + n.Op = OSLICEARR + } + n = reduceSlice(n) } + } else { n = reduceSlice(n) } @@ -1425,8 +1418,9 @@ opswitch: a := Nod(OAS, var_, nil) // zero temp a = typecheck(a, Etop) init.Append(a) - r := Nod(OSLICE, var_, Nod(OKEY, nil, l)) // arr[:l] - r = conv(r, n.Type) // in case n.Type is named. + r := Nod(OSLICE, var_, nil) // arr[:l] + r.SetSliceBounds(nil, l, nil) + r = conv(r, n.Type) // in case n.Type is named. r = typecheck(r, Erv) r = walkexpr(r, init) n = r @@ -1596,13 +1590,15 @@ opswitch: return n } +// TODO(josharian): combine this with its caller and simplify func reduceSlice(n *Node) *Node { - r := n.Right.Right - if r != nil && r.Op == OLEN && samesafeexpr(n.Left, r.Left) { + low, high, max := n.SliceBounds() + if high != nil && high.Op == OLEN && samesafeexpr(n.Left, high.Left) { // Reduce x[i:len(x)] to x[i:]. - n.Right.Right = nil + high = nil } - if (n.Op == OSLICE || n.Op == OSLICESTR) && n.Right.Left == nil && n.Right.Right == nil { + n.SetSliceBounds(low, high, max) + if (n.Op == OSLICE || n.Op == OSLICESTR) && low == nil && high == nil { // Reduce x[:] to x. if Debug_slice > 0 { Warn("slice: omit slice operation") @@ -2816,14 +2812,15 @@ func appendslice(n *Node, init *Nodes) *Node { l = append(l, nif) // s = s[:n] - nt := Nod(OSLICE, s, Nod(OKEY, nil, nn)) + nt := Nod(OSLICE, s, nil) + nt.SetSliceBounds(nil, nn, nil) nt.Etype = 1 l = append(l, Nod(OAS, s, nt)) if haspointers(l1.Type.Elem()) { // copy(s[len(l1):], l2) - nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), nil)) - + nptr1 := Nod(OSLICE, s, nil) + nptr1.SetSliceBounds(Nod(OLEN, l1, nil), nil, nil) nptr1.Etype = 1 nptr2 := l2 fn := syslook("typedslicecopy") @@ -2835,8 +2832,8 @@ func appendslice(n *Node, init *Nodes) *Node { } else if instrumenting { // rely on runtime to instrument copy. // copy(s[len(l1):], l2) - nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), nil)) - + nptr1 := Nod(OSLICE, s, nil) + nptr1.SetSliceBounds(Nod(OLEN, l1, nil), nil, nil) nptr1.Etype = 1 nptr2 := l2 var fn *Node @@ -2950,7 +2947,8 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node { nn := temp(Types[TINT]) l = append(l, Nod(OAS, nn, Nod(OLEN, ns, nil))) // n = len(s) - nx = Nod(OSLICE, ns, Nod(OKEY, nil, Nod(OADD, nn, na))) // ...s[:n+argc] + nx = Nod(OSLICE, ns, nil) // ...s[:n+argc] + nx.SetSliceBounds(nil, Nod(OADD, nn, na), nil) nx.Etype = 1 l = append(l, Nod(OAS, ns, nx)) // s = s[:n+argc]