Skip to content

Commit

Permalink
cmd/compile: allow conversion from slice to array ptr
Browse files Browse the repository at this point in the history
Panic if the slice is too short.

Updates #395

Change-Id: I90f4bff2da5d8f3148ba06d2482084f32b25c29a
Reviewed-on: https://go-review.googlesource.com/c/go/+/301650
Trust: Josh Bleecher Snyder <josharian@gmail.com>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
  • Loading branch information
josharian committed Apr 21, 2021
1 parent 1c26843 commit faa4fa1
Show file tree
Hide file tree
Showing 33 changed files with 380 additions and 141 deletions.
5 changes: 4 additions & 1 deletion src/cmd/compile/internal/escape/escape.go
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,10 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) {
k = e.spill(k, n)
}
e.expr(k.note(n, "interface-converted"), n.X)

case ir.OSLICE2ARRPTR:
// the slice pointer flows directly to the result
n := n.(*ir.ConvExpr)
e.expr(k, n.X)
case ir.ORECV:
n := n.(*ir.UnaryExpr)
e.discard(n.X)
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/ir/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ func (n *ConvExpr) SetOp(op Op) {
switch op {
default:
panic(n.no("SetOp " + op.String()))
case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, OBYTES2STRTMP, ORUNES2STR, OSTR2BYTES, OSTR2BYTESTMP, OSTR2RUNES, ORUNESTR:
case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, OBYTES2STRTMP, ORUNES2STR, OSTR2BYTES, OSTR2BYTESTMP, OSTR2RUNES, ORUNESTR, OSLICE2ARRPTR:
n.op = op
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/cmd/compile/internal/ir/fmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ var OpPrec = []int{
OPRINT: 8,
ORUNESTR: 8,
OSIZEOF: 8,
OSLICE2ARRPTR: 8,
OSTR2BYTES: 8,
OSTR2RUNES: 8,
OSTRUCTLIT: 8,
Expand Down Expand Up @@ -804,7 +805,8 @@ func exprFmt(n Node, s fmt.State, prec int) {
ORUNES2STR,
OSTR2BYTES,
OSTR2RUNES,
ORUNESTR:
ORUNESTR,
OSLICE2ARRPTR:
n := n.(*ConvExpr)
if n.Type() == nil || n.Type().Sym() == nil {
fmt.Fprintf(s, "(%v)", n.Type())
Expand Down
1 change: 1 addition & 0 deletions src/cmd/compile/internal/ir/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ const (
OSTR2BYTES // Type(Left) (Type is []byte, Left is a string)
OSTR2BYTESTMP // Type(Left) (Type is []byte, Left is a string, ephemeral)
OSTR2RUNES // Type(Left) (Type is []rune, Left is a string)
OSLICE2ARRPTR // Type(Left) (Type is *[N]T, Left is a []T)
// Left = Right or (if Colas=true) Left := Right
// If Colas, then Ninit includes a DCL node for Left.
OAS
Expand Down
269 changes: 135 additions & 134 deletions src/cmd/compile/internal/ir/op_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/cmd/compile/internal/ssa/expand_calls.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ func (x *expandState) rewriteSelect(leaf *Value, selector *Value, offset int64,
ls := x.rewriteSelect(leaf, selector.Args[0], offset, regOffset)
locs = x.splitSlots(ls, ".ptr", 0, x.typs.BytePtr)

case OpSlicePtr:
case OpSlicePtr, OpSlicePtrUnchecked:
w := selector.Args[0]
ls := x.rewriteSelect(leaf, w, offset, regOffset)
locs = x.splitSlots(ls, ".ptr", 0, types.NewPtr(w.Type.Elem()))
Expand Down Expand Up @@ -1202,7 +1202,7 @@ func expandCalls(f *Func) {
case OpStructSelect, OpArraySelect,
OpIData, OpITab,
OpStringPtr, OpStringLen,
OpSlicePtr, OpSliceLen, OpSliceCap,
OpSlicePtr, OpSliceLen, OpSliceCap, OpSlicePtrUnchecked,
OpComplexReal, OpComplexImag,
OpInt64Hi, OpInt64Lo:
w := v.Args[0]
Expand Down
1 change: 1 addition & 0 deletions src/cmd/compile/internal/ssa/gen/dec.rules
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
(SlicePtr (SliceMake ptr _ _ )) => ptr
(SliceLen (SliceMake _ len _)) => len
(SliceCap (SliceMake _ _ cap)) => cap
(SlicePtrUnchecked (SliceMake ptr _ _ )) => ptr

(Load <t> ptr mem) && t.IsSlice() =>
(SliceMake
Expand Down
4 changes: 4 additions & 0 deletions src/cmd/compile/internal/ssa/gen/genericOps.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,10 @@ var genericOps = []opData{
{name: "SlicePtr", argLength: 1, typ: "BytePtr"}, // ptr(arg0)
{name: "SliceLen", argLength: 1}, // len(arg0)
{name: "SliceCap", argLength: 1}, // cap(arg0)
// SlicePtrUnchecked, like SlicePtr, extracts the pointer from a slice.
// SlicePtr values are assumed non-nil, because they are guarded by bounds checks.
// SlicePtrUnchecked values can be nil.
{name: "SlicePtrUnchecked", argLength: 1},

// Complex (part/whole)
{name: "ComplexMake", argLength: 2}, // arg0=real, arg1=imag
Expand Down
4 changes: 3 additions & 1 deletion src/cmd/compile/internal/ssa/op.go
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ const (
BoundsSlice3BU // ... with unsigned high
BoundsSlice3C // 3-arg slicing operation, 0 <= low <= high failed
BoundsSlice3CU // ... with unsigned low
BoundsConvert // conversion to array pointer failed
BoundsKindCount
)

Expand Down Expand Up @@ -496,7 +497,8 @@ func boundsABI(b int64) int {
case BoundsSlice3Alen,
BoundsSlice3AlenU,
BoundsSlice3Acap,
BoundsSlice3AcapU:
BoundsSlice3AcapU,
BoundsConvert:
return 0
case BoundsSliceAlen,
BoundsSliceAlenU,
Expand Down
Loading

0 comments on commit faa4fa1

Please sign in to comment.