diff options
author | Matthew Dempsky <mdempsky@google.com> | 2021-04-21 02:11:15 -0700 |
---|---|---|
committer | Matthew Dempsky <mdempsky@google.com> | 2021-05-02 20:38:13 +0000 |
commit | fadad851a3222867b374e901ede9c4919594837f (patch) | |
tree | 7b4efe046ea2da139b27ce5091d0cbd058bdf331 /src/cmd/compile/internal/walk | |
parent | 0d32d9e8a8784cf3ef39c471b73e502c51085b6d (diff) | |
download | go-fadad851a3222867b374e901ede9c4919594837f.tar.gz go-fadad851a3222867b374e901ede9c4919594837f.zip |
cmd/compile: implement unsafe.Add and unsafe.Slice
Updates #19367.
Updates #40481.
Change-Id: Iabd2afdd0d520e5d68fd9e6dedd013335a4b3886
Reviewed-on: https://go-review.googlesource.com/c/go/+/312214
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Trust: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.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 | 39 | ||||
-rw-r--r-- | src/cmd/compile/internal/walk/expr.go | 7 |
2 files changed, 45 insertions, 1 deletions
diff --git a/src/cmd/compile/internal/walk/builtin.go b/src/cmd/compile/internal/walk/builtin.go index aacdedcb4d..62eb4298f4 100644 --- a/src/cmd/compile/internal/walk/builtin.go +++ b/src/cmd/compile/internal/walk/builtin.go @@ -653,6 +653,45 @@ func walkRecover(nn *ir.CallExpr, init *ir.Nodes) ir.Node { return mkcall("gorecover", nn.Type(), init, fp) } +func walkUnsafeSlice(n *ir.BinaryExpr, init *ir.Nodes) ir.Node { + len := safeExpr(n.Y, init) + + fnname := "unsafeslice64" + argtype := 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() { + fnname = "unsafeslice" + argtype = 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. + 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. + + h := ir.NewSliceHeaderExpr(n.Pos(), t, + typecheck.Conv(ptr, types.Types[types.TUNSAFEPTR]), + typecheck.Conv(len, types.Types[types.TINT]), + typecheck.Conv(len, types.Types[types.TINT])) + return walkExpr(typecheck.Expr(h), init) +} + func badtype(op ir.Op, tl, tr *types.Type) { var s string if tl != nil { diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index 5a1a2441bf..2fb907710b 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -117,12 +117,17 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node { n.X = walkExpr(n.X, init) return n - case ir.OEFACE, ir.OAND, ir.OANDNOT, ir.OSUB, ir.OMUL, ir.OADD, ir.OOR, ir.OXOR, ir.OLSH, ir.ORSH: + case ir.OEFACE, ir.OAND, ir.OANDNOT, ir.OSUB, ir.OMUL, ir.OADD, ir.OOR, ir.OXOR, ir.OLSH, ir.ORSH, + ir.OUNSAFEADD: n := n.(*ir.BinaryExpr) n.X = walkExpr(n.X, init) n.Y = walkExpr(n.Y, init) return n + case ir.OUNSAFESLICE: + n := n.(*ir.BinaryExpr) + return walkUnsafeSlice(n, init) + case ir.ODOT, ir.ODOTPTR: n := n.(*ir.SelectorExpr) return walkDot(n, init) |