mirror of
https://github.com/golang/go
synced 2024-11-24 05:20:04 -07:00
cmd/compile/internal/gc: minor cleanup of slicing
Tidy the code up a little bit to move variable definitions closer to uses, prefer early return to else branches and some other minor tweaks. I'd like to make some more changes to this code in the near future and this CL should make those changes cleaner. Change-Id: Ie7d7f2e4bb1e670347941e255c9cdc1703282db5 Reviewed-on: https://go-review.googlesource.com/c/go/+/170120 Run-TryBot: Michael Munday <mike.munday@ibm.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
parent
5fc55b3180
commit
726a9398f7
@ -2415,7 +2415,7 @@ func (s *state) expr(n *Node) *ssa.Value {
|
||||
if max != nil {
|
||||
k = s.expr(max)
|
||||
}
|
||||
p, l, c := s.slice(n.Left.Type, v, i, j, k, n.Bounded())
|
||||
p, l, c := s.slice(v, i, j, k, n.Bounded())
|
||||
return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c)
|
||||
|
||||
case OSLICESTR:
|
||||
@ -2428,7 +2428,7 @@ func (s *state) expr(n *Node) *ssa.Value {
|
||||
if high != nil {
|
||||
j = s.expr(high)
|
||||
}
|
||||
p, l, _ := s.slice(n.Left.Type, v, i, j, nil, n.Bounded())
|
||||
p, l, _ := s.slice(v, i, j, nil, n.Bounded())
|
||||
return s.newValue2(ssa.OpStringMake, n.Type, p, l)
|
||||
|
||||
case OCALLFUNC:
|
||||
@ -4359,35 +4359,25 @@ func (s *state) storeArg(n *Node, t *types.Type, off int64) {
|
||||
|
||||
// slice computes the slice v[i:j:k] and returns ptr, len, and cap of result.
|
||||
// i,j,k may be nil, in which case they are set to their default value.
|
||||
// t is a slice, ptr to array, or string type.
|
||||
func (s *state) slice(t *types.Type, v, i, j, k *ssa.Value, bounded bool) (p, l, c *ssa.Value) {
|
||||
var elemtype *types.Type
|
||||
var ptrtype *types.Type
|
||||
var ptr *ssa.Value
|
||||
var len *ssa.Value
|
||||
var cap *ssa.Value
|
||||
zero := s.constInt(types.Types[TINT], 0)
|
||||
// v may be a slice, string or pointer to an array.
|
||||
func (s *state) slice(v, i, j, k *ssa.Value, bounded bool) (p, l, c *ssa.Value) {
|
||||
t := v.Type
|
||||
var ptr, len, cap *ssa.Value
|
||||
switch {
|
||||
case t.IsSlice():
|
||||
elemtype = t.Elem()
|
||||
ptrtype = types.NewPtr(elemtype)
|
||||
ptr = s.newValue1(ssa.OpSlicePtr, ptrtype, v)
|
||||
ptr = s.newValue1(ssa.OpSlicePtr, types.NewPtr(t.Elem()), v)
|
||||
len = s.newValue1(ssa.OpSliceLen, types.Types[TINT], v)
|
||||
cap = s.newValue1(ssa.OpSliceCap, types.Types[TINT], v)
|
||||
case t.IsString():
|
||||
elemtype = types.Types[TUINT8]
|
||||
ptrtype = types.NewPtr(elemtype)
|
||||
ptr = s.newValue1(ssa.OpStringPtr, ptrtype, v)
|
||||
ptr = s.newValue1(ssa.OpStringPtr, types.NewPtr(types.Types[TUINT8]), v)
|
||||
len = s.newValue1(ssa.OpStringLen, types.Types[TINT], v)
|
||||
cap = len
|
||||
case t.IsPtr():
|
||||
if !t.Elem().IsArray() {
|
||||
s.Fatalf("bad ptr to array in slice %v\n", t)
|
||||
}
|
||||
elemtype = t.Elem().Elem()
|
||||
ptrtype = types.NewPtr(elemtype)
|
||||
s.nilCheck(v)
|
||||
ptr = v
|
||||
ptr = s.newValue1(ssa.OpCopy, types.NewPtr(t.Elem().Elem()), v)
|
||||
len = s.constInt(types.Types[TINT], t.Elem().NumElem())
|
||||
cap = len
|
||||
default:
|
||||
@ -4396,7 +4386,7 @@ func (s *state) slice(t *types.Type, v, i, j, k *ssa.Value, bounded bool) (p, l,
|
||||
|
||||
// Set default values
|
||||
if i == nil {
|
||||
i = zero
|
||||
i = s.constInt(types.Types[TINT], 0)
|
||||
}
|
||||
if j == nil {
|
||||
j = len
|
||||
@ -4433,47 +4423,53 @@ func (s *state) slice(t *types.Type, v, i, j, k *ssa.Value, bounded bool) (p, l,
|
||||
i = s.boundsCheck(i, j, ssa.BoundsSliceB, bounded)
|
||||
}
|
||||
|
||||
// Generate the following code assuming that indexes are in bounds.
|
||||
// The masking is to make sure that we don't generate a slice
|
||||
// that points to the next object in memory.
|
||||
// rlen = j - i
|
||||
// rcap = k - i
|
||||
// delta = i * elemsize
|
||||
// rptr = p + delta&mask(rcap)
|
||||
// result = (SliceMake rptr rlen rcap)
|
||||
// where mask(x) is 0 if x==0 and -1 if x>0.
|
||||
// Word-sized integer operations.
|
||||
subOp := s.ssaOp(OSUB, types.Types[TINT])
|
||||
mulOp := s.ssaOp(OMUL, types.Types[TINT])
|
||||
andOp := s.ssaOp(OAND, types.Types[TINT])
|
||||
|
||||
// Calculate the length (rlen) and capacity (rcap) of the new slice.
|
||||
// For strings the capacity of the result is unimportant. However,
|
||||
// we use rcap to test if we've generated a zero-length slice.
|
||||
// Use length of strings for that.
|
||||
rlen := s.newValue2(subOp, types.Types[TINT], j, i)
|
||||
var rcap *ssa.Value
|
||||
switch {
|
||||
case t.IsString():
|
||||
// Capacity of the result is unimportant. However, we use
|
||||
// rcap to test if we've generated a zero-length slice.
|
||||
// Use length of strings for that.
|
||||
rcap = rlen
|
||||
case j == k:
|
||||
rcap = rlen
|
||||
default:
|
||||
rcap := rlen
|
||||
if j != k && !t.IsString() {
|
||||
rcap = s.newValue2(subOp, types.Types[TINT], k, i)
|
||||
}
|
||||
|
||||
var rptr *ssa.Value
|
||||
if (i.Op == ssa.OpConst64 || i.Op == ssa.OpConst32) && i.AuxInt == 0 {
|
||||
// No pointer arithmetic necessary.
|
||||
rptr = ptr
|
||||
} else {
|
||||
// delta = # of bytes to offset pointer by.
|
||||
delta := s.newValue2(mulOp, types.Types[TINT], i, s.constInt(types.Types[TINT], elemtype.Width))
|
||||
// If we're slicing to the point where the capacity is zero,
|
||||
// zero out the delta.
|
||||
mask := s.newValue1(ssa.OpSlicemask, types.Types[TINT], rcap)
|
||||
delta = s.newValue2(andOp, types.Types[TINT], delta, mask)
|
||||
// Compute rptr = ptr + delta
|
||||
rptr = s.newValue2(ssa.OpAddPtr, ptrtype, ptr, delta)
|
||||
return ptr, rlen, rcap
|
||||
}
|
||||
|
||||
// Calculate the base pointer (rptr) for the new slice.
|
||||
//
|
||||
// Generate the following code assuming that indexes are in bounds.
|
||||
// The masking is to make sure that we don't generate a slice
|
||||
// that points to the next object in memory. We cannot just set
|
||||
// the pointer to nil because then we would create a nil slice or
|
||||
// string.
|
||||
//
|
||||
// rcap = k - i
|
||||
// rlen = j - i
|
||||
// rptr = ptr + (mask(rcap) & (i * stride))
|
||||
//
|
||||
// Where mask(x) is 0 if x==0 and -1 if x>0 and stride is the width
|
||||
// of the element type.
|
||||
stride := s.constInt(types.Types[TINT], ptr.Type.Elem().Width)
|
||||
|
||||
// The delta is the number of bytes to offset ptr by.
|
||||
delta := s.newValue2(mulOp, types.Types[TINT], i, stride)
|
||||
|
||||
// If we're slicing to the point where the capacity is zero,
|
||||
// zero out the delta.
|
||||
mask := s.newValue1(ssa.OpSlicemask, types.Types[TINT], rcap)
|
||||
delta = s.newValue2(andOp, types.Types[TINT], delta, mask)
|
||||
|
||||
// Compute rptr = ptr + delta.
|
||||
rptr := s.newValue2(ssa.OpAddPtr, ptr.Type, ptr, delta)
|
||||
|
||||
return rptr, rlen, rcap
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user