aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/walk
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2021-04-21 02:11:15 -0700
committerMatthew Dempsky <mdempsky@google.com>2021-05-02 20:38:13 +0000
commitfadad851a3222867b374e901ede9c4919594837f (patch)
tree7b4efe046ea2da139b27ce5091d0cbd058bdf331 /src/cmd/compile/internal/walk
parent0d32d9e8a8784cf3ef39c471b73e502c51085b6d (diff)
downloadgo-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.go39
-rw-r--r--src/cmd/compile/internal/walk/expr.go7
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)