diff options
author | Matthew Dempsky <mdempsky@google.com> | 2021-06-25 11:07:28 -0700 |
---|---|---|
committer | Matthew Dempsky <mdempsky@google.com> | 2021-06-28 23:31:13 +0000 |
commit | 4bb0847b088eb3eb6122a18a87e1ca7756281dcc (patch) | |
tree | 9baa7b329f0ec4cfdc2f80a833e14070794fe76c /src/cmd/compile/internal/walk | |
parent | 1519271a939ad27da133318dc4bde7e6a41a35b5 (diff) | |
download | go-4bb0847b088eb3eb6122a18a87e1ca7756281dcc.tar.gz go-4bb0847b088eb3eb6122a18a87e1ca7756281dcc.zip |
cmd/compile,runtime: change unsafe.Slice((*T)(nil), 0) to return []T(nil)
This CL removes the unconditional OCHECKNIL check added in
walkUnsafeSlice by instead passing it as a pointer to
runtime.unsafeslice, and hiding the check behind a `len == 0` check.
While here, this CL also implements checkptr functionality for
unsafe.Slice and disallows use of unsafe.Slice with //go:notinheap
types.
Updates #46742.
Change-Id: I743a445ac124304a4d7322a7fe089c4a21b9a655
Reviewed-on: https://go-review.googlesource.com/c/go/+/331070
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/walk')
-rw-r--r-- | src/cmd/compile/internal/walk/builtin.go | 26 |
1 files changed, 9 insertions, 17 deletions
diff --git a/src/cmd/compile/internal/walk/builtin.go b/src/cmd/compile/internal/walk/builtin.go index 62eb4298f4..1f08e4d312 100644 --- a/src/cmd/compile/internal/walk/builtin.go +++ b/src/cmd/compile/internal/walk/builtin.go @@ -654,36 +654,28 @@ func walkRecover(nn *ir.CallExpr, init *ir.Nodes) ir.Node { } func walkUnsafeSlice(n *ir.BinaryExpr, init *ir.Nodes) ir.Node { + ptr := safeExpr(n.X, init) len := safeExpr(n.Y, init) fnname := "unsafeslice64" - argtype := types.Types[types.TINT64] + lenType := types.Types[types.TINT64] // Type checking guarantees that TIDEAL len/cap are positive and fit in an int. // The case of len or cap overflow when converting TUINT or TUINTPTR to TINT // will be handled by the negative range checks in unsafeslice during runtime. - if len.Type().IsKind(types.TIDEAL) || len.Type().Size() <= types.Types[types.TUINT].Size() { + if ir.ShouldCheckPtr(ir.CurFunc, 1) { + fnname = "unsafeslicecheckptr" + // for simplicity, unsafeslicecheckptr always uses int64 + } else if len.Type().IsKind(types.TIDEAL) || len.Type().Size() <= types.Types[types.TUINT].Size() { fnname = "unsafeslice" - argtype = types.Types[types.TINT] + lenType = types.Types[types.TINT] } t := n.Type() - // Call runtime.unsafeslice[64] to check that the length argument is - // non-negative and smaller than the max length allowed for the - // element type. + // Call runtime.unsafeslice{,64,checkptr} to check ptr and len. fn := typecheck.LookupRuntime(fnname) - init.Append(mkcall1(fn, nil, init, reflectdata.TypePtr(t.Elem()), typecheck.Conv(len, argtype))) - - ptr := walkExpr(n.X, init) - - c := ir.NewUnaryExpr(n.Pos(), ir.OCHECKNIL, ptr) - c.SetTypecheck(1) - init.Append(c) - - // TODO(mdempsky): checkptr instrumentation. Maybe merge into length - // check above, along with nil check? Need to be careful about - // notinheap pointers though: can't pass them as unsafe.Pointer. + init.Append(mkcall1(fn, nil, init, reflectdata.TypePtr(t.Elem()), typecheck.Conv(ptr, types.Types[types.TUNSAFEPTR]), typecheck.Conv(len, lenType))) h := ir.NewSliceHeaderExpr(n.Pos(), t, typecheck.Conv(ptr, types.Types[types.TUNSAFEPTR]), |