summaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/walk/builtin.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/walk/builtin.go')
-rw-r--r--src/cmd/compile/internal/walk/builtin.go39
1 files changed, 39 insertions, 0 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 {