})
}
}
+
+// Test cases copied from ../../test/unsafebuiltins.go
+func TestSliceAt(t *testing.T) {
+ const maxUintptr = 1 << (8 * unsafe.Sizeof(uintptr(0)))
+ var p [10]byte
+
+ typ := TypeOf(p[0])
+
+ s := SliceAt(typ, unsafe.Pointer(&p[0]), len(p))
+ if s.Pointer() != uintptr(unsafe.Pointer(&p[0])) {
+ t.Fatalf("unexpected underlying array: %d, want: %d", s.Pointer(), uintptr(unsafe.Pointer(&p[0])))
+ }
+ if s.Len() != len(p) || s.Cap() != len(p) {
+ t.Fatalf("unexpected len or cap, len: %d, cap: %d, want: %d", s.Len(), s.Cap(), len(p))
+ }
+
+ typ = TypeOf(0)
+ if !SliceAt(typ, unsafe.Pointer((*int)(nil)), 0).IsNil() {
+ t.Fatal("nil pointer with zero length must return nil")
+ }
+
+ // nil pointer with positive length panics
+ shouldPanic("", func() { _ = SliceAt(typ, unsafe.Pointer((*int)(nil)), 1) })
+
+ // negative length
+ var neg int = -1
+ shouldPanic("", func() { _ = SliceAt(TypeOf(byte(0)), unsafe.Pointer(&p[0]), neg) })
+
+ // size overflows address space
+ n := uint64(0)
+ shouldPanic("", func() { _ = SliceAt(TypeOf(n), unsafe.Pointer(&n), maxUintptr/8) })
+ shouldPanic("", func() { _ = SliceAt(TypeOf(n), unsafe.Pointer(&n), maxUintptr/8+1) })
+
+ // sliced memory overflows address space
+ last := (*byte)(unsafe.Pointer(^uintptr(0)))
+ // This panics here, but won't panic in ../../test/unsafebuiltins.go,
+ // because unsafe.Slice(last, 1) does not escape.
+ //
+ // _ = SliceAt(typ, unsafe.Pointer(last), 1)
+ shouldPanic("", func() { _ = SliceAt(typ, unsafe.Pointer(last), 2) })
+}
return Value{&typ.(*rtype).t, unsafe.Pointer(&s), flagIndir | flag(Slice)}
}
+// SliceAt returns a [Value] representing a slice whose underlying
+// data starts at p, with length and capacity equal to n.
+//
+// This is like [unsafe.Slice].
+func SliceAt(typ Type, p unsafe.Pointer, n int) Value {
+ unsafeslice(typ.common(), p, n)
+ s := unsafeheader.Slice{Data: p, Len: n, Cap: n}
+ return Value{SliceOf(typ).common(), unsafe.Pointer(&s), flagIndir | flag(Slice)}
+}
+
// MakeChan creates a new channel with the specified type and buffer size.
func MakeChan(typ Type, buffer int) Value {
if typ.Kind() != Chan {
//go:noescape
func growslice(t *abi.Type, old unsafeheader.Slice, num int) unsafeheader.Slice
+//go:noescape
+func unsafeslice(t *abi.Type, ptr unsafe.Pointer, len int)
+
// Dummy annotation marking that the value x escapes,
// for use in cases where the reflect code is so clever that
// the compiler cannot follow.
panicCheck1(pc, "unsafe.Slice: ptr is nil and len is not zero")
panic(errorString("unsafe.Slice: ptr is nil and len is not zero"))
}
+
+//go:linkname reflect_unsafeslice reflect.unsafeslice
+func reflect_unsafeslice(et *_type, ptr unsafe.Pointer, len int) {
+ unsafeslice(et, ptr, len)
+}