patch reflect

This commit is contained in:
xushiwei
2024-07-04 17:29:40 +08:00
parent ab1d05642e
commit 7e25ec1ac3

View File

@@ -21,6 +21,7 @@
package reflect
import (
"errors"
"unsafe"
"github.com/goplus/llgo/internal/abi"
@@ -357,6 +358,260 @@ func (v Value) bytesSlow() []byte {
panic("todo")
}
// runes returns v's underlying value.
// It panics if v's underlying value is not a slice of runes (int32s).
func (v Value) runes() []rune {
v.mustBe(Slice)
if v.typ().Elem().Kind() != abi.Int32 {
panic("reflect.Value.Bytes of non-rune slice")
}
// Slice is always bigger than a word; assume flagIndir.
return *(*[]rune)(v.ptr)
}
// CanAddr reports whether the value's address can be obtained with Addr.
// Such values are called addressable. A value is addressable if it is
// an element of a slice, an element of an addressable array,
// a field of an addressable struct, or the result of dereferencing a pointer.
// If CanAddr returns false, calling Addr will panic.
func (v Value) CanAddr() bool {
return v.flag&flagAddr != 0
}
// CanSet reports whether the value of v can be changed.
// A Value can be changed only if it is addressable and was not
// obtained by the use of unexported struct fields.
// If CanSet returns false, calling Set or any type-specific
// setter (e.g., SetBool, SetInt) will panic.
func (v Value) CanSet() bool {
return v.flag&(flagAddr|flagRO) == flagAddr
}
// Cap returns v's capacity.
// It panics if v's Kind is not Array, Chan, Slice or pointer to Array.
func (v Value) Cap() int {
/* TODO(xsw):
// capNonSlice is split out to keep Cap inlineable for slice kinds.
if v.kind() == Slice {
return (*unsafeheader.Slice)(v.ptr).Cap
}
return v.capNonSlice()
*/
panic("todo: reflect.Value.Cap")
}
func (v Value) capNonSlice() int {
/* TODO(xsw):
k := v.kind()
switch k {
case Array:
return v.typ().Len()
case Chan:
return chancap(v.pointer())
case Ptr:
if v.typ().Elem().Kind() == abi.Array {
return v.typ().Elem().Len()
}
panic("reflect: call of reflect.Value.Cap on ptr to non-array Value")
}
panic(&ValueError{"reflect.Value.Cap", v.kind()})
*/
panic("todo: reflect.Value.capNonSlice")
}
// Close closes the channel v.
// It panics if v's Kind is not Chan.
func (v Value) Close() {
/* TODO(xsw):
v.mustBe(Chan)
v.mustBeExported()
chanclose(v.pointer())
*/
panic("todo: reflect.Value.Close")
}
// CanComplex reports whether Complex can be used without panicking.
func (v Value) CanComplex() bool {
switch v.kind() {
case Complex64, Complex128:
return true
default:
return false
}
}
// Complex returns v's underlying value, as a complex128.
// It panics if v's Kind is not Complex64 or Complex128
func (v Value) Complex() complex128 {
k := v.kind()
switch k {
case Complex64:
return complex128(*(*complex64)(v.ptr))
case Complex128:
return *(*complex128)(v.ptr)
}
panic(&ValueError{"reflect.Value.Complex", v.kind()})
}
// Elem returns the value that the interface v contains
// or that the pointer v points to.
// It panics if v's Kind is not Interface or Pointer.
// It returns the zero Value if v is nil.
func (v Value) Elem() Value {
/* TODO(xsw):
k := v.kind()
switch k {
case Interface:
var eface any
if v.typ().NumMethod() == 0 {
eface = *(*any)(v.ptr)
} else {
eface = (any)(*(*interface {
M()
})(v.ptr))
}
x := unpackEface(eface)
if x.flag != 0 {
x.flag |= v.flag.ro()
}
return x
case Pointer:
ptr := v.ptr
if v.flag&flagIndir != 0 {
if ifaceIndir(v.typ()) {
// This is a pointer to a not-in-heap object. ptr points to a uintptr
// in the heap. That uintptr is the address of a not-in-heap object.
// In general, pointers to not-in-heap objects can be total junk.
// But Elem() is asking to dereference it, so the user has asserted
// that at least it is a valid pointer (not just an integer stored in
// a pointer slot). So let's check, to make sure that it isn't a pointer
// that the runtime will crash on if it sees it during GC or write barriers.
// Since it is a not-in-heap pointer, all pointers to the heap are
// forbidden! That makes the test pretty easy.
// See issue 48399.
if !verifyNotInHeapPtr(*(*uintptr)(ptr)) {
panic("reflect: reflect.Value.Elem on an invalid notinheap pointer")
}
}
ptr = *(*unsafe.Pointer)(ptr)
}
// The returned value's address is v's value.
if ptr == nil {
return Value{}
}
tt := (*ptrType)(unsafe.Pointer(v.typ()))
typ := tt.Elem
fl := v.flag&flagRO | flagIndir | flagAddr
fl |= flag(typ.Kind())
return Value{typ, ptr, fl}
}
panic(&ValueError{"reflect.Value.Elem", v.kind()})
*/
panic("todo: reflect.Value.Elem")
}
// Field returns the i'th field of the struct v.
// It panics if v's Kind is not Struct or i is out of range.
func (v Value) Field(i int) Value {
/* TODO(xsw):
if v.kind() != Struct {
panic(&ValueError{"reflect.Value.Field", v.kind()})
}
tt := (*structType)(unsafe.Pointer(v.typ()))
if uint(i) >= uint(len(tt.Fields)) {
panic("reflect: Field index out of range")
}
field := &tt.Fields[i]
typ := field.Typ
// Inherit permission bits from v, but clear flagEmbedRO.
fl := v.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind())
// Using an unexported field forces flagRO.
if !field.Name.IsExported() {
if field.Embedded() {
fl |= flagEmbedRO
} else {
fl |= flagStickyRO
}
}
// Either flagIndir is set and v.ptr points at struct,
// or flagIndir is not set and v.ptr is the actual struct data.
// In the former case, we want v.ptr + offset.
// In the latter case, we must have field.offset = 0,
// so v.ptr + field.offset is still the correct address.
ptr := add(v.ptr, field.Offset, "same as non-reflect &v.field")
return Value{typ, ptr, fl}
*/
panic("todo: reflect.Value.Field")
}
// FieldByIndex returns the nested field corresponding to index.
// It panics if evaluation requires stepping through a nil
// pointer or a field that is not a struct.
func (v Value) FieldByIndex(index []int) Value {
if len(index) == 1 {
return v.Field(index[0])
}
v.mustBe(Struct)
for i, x := range index {
if i > 0 {
if v.Kind() == Pointer && v.typ().Elem().Kind() == abi.Struct {
if v.IsNil() {
panic("reflect: indirection through nil pointer to embedded struct")
}
v = v.Elem()
}
}
v = v.Field(x)
}
return v
}
// FieldByIndexErr returns the nested field corresponding to index.
// It returns an error if evaluation requires stepping through a nil
// pointer, but panics if it must step through a field that
// is not a struct.
func (v Value) FieldByIndexErr(index []int) (Value, error) {
if len(index) == 1 {
return v.Field(index[0]), nil
}
v.mustBe(Struct)
for i, x := range index {
if i > 0 {
if v.Kind() == Ptr && v.typ().Elem().Kind() == abi.Struct {
if v.IsNil() {
return Value{}, errors.New("reflect: indirection through nil pointer to embedded struct field " + nameFor(v.typ().Elem()))
}
v = v.Elem()
}
}
v = v.Field(x)
}
return v, nil
}
// FieldByName returns the struct field with the given name.
// It returns the zero Value if no field was found.
// It panics if v's Kind is not struct.
func (v Value) FieldByName(name string) Value {
v.mustBe(Struct)
if f, ok := toRType(v.typ()).FieldByName(name); ok {
return v.FieldByIndex(f.Index)
}
return Value{}
}
// FieldByNameFunc returns the struct field with a name
// that satisfies the match function.
// It panics if v's Kind is not struct.
// It returns the zero Value if no field was found.
func (v Value) FieldByNameFunc(match func(string) bool) Value {
if f, ok := toRType(v.typ()).FieldByNameFunc(match); ok {
return v.FieldByIndex(f.Index)
}
return Value{}
}
// CanFloat reports whether Float can be used without panicking.
func (v Value) CanFloat() bool {
switch v.kind() {
@@ -746,6 +1001,133 @@ func (v Value) lenNonSlice() int {
panic("todo")
}
// Pointer returns v's value as a uintptr.
// It panics if v's Kind is not Chan, Func, Map, Pointer, Slice, or UnsafePointer.
//
// If v's Kind is Func, the returned pointer is an underlying
// code pointer, but not necessarily enough to identify a
// single function uniquely. The only guarantee is that the
// result is zero if and only if v is a nil func Value.
//
// If v's Kind is Slice, the returned pointer is to the first
// element of the slice. If the slice is nil the returned value
// is 0. If the slice is empty but non-nil the return value is non-zero.
//
// It's preferred to use uintptr(Value.UnsafePointer()) to get the equivalent result.
func (v Value) Pointer() uintptr {
/* TODO(xsw):
// The compiler loses track as it converts to uintptr. Force escape.
escapes(v.ptr)
k := v.kind()
switch k {
case Pointer:
if v.typ().PtrBytes == 0 {
val := *(*uintptr)(v.ptr)
// Since it is a not-in-heap pointer, all pointers to the heap are
// forbidden! See comment in Value.Elem and issue #48399.
if !verifyNotInHeapPtr(val) {
panic("reflect: reflect.Value.Pointer on an invalid notinheap pointer")
}
return val
}
fallthrough
case Chan, Map, UnsafePointer:
return uintptr(v.pointer())
case Func:
if v.flag&flagMethod != 0 {
// As the doc comment says, the returned pointer is an
// underlying code pointer but not necessarily enough to
// identify a single function uniquely. All method expressions
// created via reflect have the same underlying code pointer,
// so their Pointers are equal. The function used here must
// match the one used in makeMethodValue.
return methodValueCallCodePtr()
}
p := v.pointer()
// Non-nil func value points at data block.
// First word of data block is actual code.
if p != nil {
p = *(*unsafe.Pointer)(p)
}
return uintptr(p)
case Slice:
return uintptr((*unsafeheader.Slice)(v.ptr).Data)
}
panic(&ValueError{"reflect.Value.Pointer", v.kind()})
*/
panic("todo: reflect.Value.Pointer")
}
// Recv receives and returns a value from the channel v.
// It panics if v's Kind is not Chan.
// The receive blocks until a value is ready.
// The boolean value ok is true if the value x corresponds to a send
// on the channel, false if it is a zero value received because the channel is closed.
func (v Value) Recv() (x Value, ok bool) {
v.mustBe(Chan)
v.mustBeExported()
return v.recv(false)
}
// internal recv, possibly non-blocking (nb).
// v is known to be a channel.
func (v Value) recv(nb bool) (val Value, ok bool) {
/* TODO(xsw):
tt := (*chanType)(unsafe.Pointer(v.typ()))
if ChanDir(tt.Dir)&RecvDir == 0 {
panic("reflect: recv on send-only channel")
}
t := tt.Elem
val = Value{t, nil, flag(t.Kind())}
var p unsafe.Pointer
if ifaceIndir(t) {
p = unsafe_New(t)
val.ptr = p
val.flag |= flagIndir
} else {
p = unsafe.Pointer(&val.ptr)
}
selected, ok := chanrecv(v.pointer(), nb, p)
if !selected {
val = Value{}
}
return
*/
panic("todo: reflect.Value.recv")
}
// Send sends x on the channel v.
// It panics if v's kind is not Chan or if x's type is not the same type as v's element type.
// As in Go, x's value must be assignable to the channel's element type.
func (v Value) Send(x Value) {
v.mustBe(Chan)
v.mustBeExported()
v.send(x, false)
}
// internal send, possibly non-blocking.
// v is known to be a channel.
func (v Value) send(x Value, nb bool) (selected bool) {
/* TODO(xsw):
tt := (*chanType)(unsafe.Pointer(v.typ()))
if ChanDir(tt.Dir)&SendDir == 0 {
panic("reflect: send on recv-only channel")
}
x.mustBeExported()
x = x.assignTo("reflect.Value.Send", tt.Elem, nil)
var p unsafe.Pointer
if x.flag&flagIndir != 0 {
p = x.ptr
} else {
p = unsafe.Pointer(&x.ptr)
}
return chansend(v.pointer(), p, nb)
*/
panic("todo: reflect.Value.send")
}
// Set assigns x to the value v.
// It panics if CanSet returns false.
// As in Go, x's value must be assignable to v's type and
@@ -847,6 +1229,448 @@ func (v Value) SetInt(x int64) {
}
}
// SetLen sets v's length to n.
// It panics if v's Kind is not Slice or if n is negative or
// greater than the capacity of the slice.
func (v Value) SetLen(n int) {
/* TODO(xsw):
v.mustBeAssignable()
v.mustBe(Slice)
s := (*unsafeheader.Slice)(v.ptr)
if uint(n) > uint(s.Cap) {
panic("reflect: slice length out of range in SetLen")
}
s.Len = n
*/
panic("todo: reflect.Value.SetLen")
}
// SetCap sets v's capacity to n.
// It panics if v's Kind is not Slice or if n is smaller than the length or
// greater than the capacity of the slice.
func (v Value) SetCap(n int) {
/* TODO(xsw):
v.mustBeAssignable()
v.mustBe(Slice)
s := (*unsafeheader.Slice)(v.ptr)
if n < s.Len || n > s.Cap {
panic("reflect: slice capacity out of range in SetCap")
}
s.Cap = n
*/
panic("todo: reflect.Value.SetCap")
}
// SetMapIndex sets the element associated with key in the map v to elem.
// It panics if v's Kind is not Map.
// If elem is the zero Value, SetMapIndex deletes the key from the map.
// Otherwise if v holds a nil map, SetMapIndex will panic.
// As in Go, key's elem must be assignable to the map's key type,
// and elem's value must be assignable to the map's elem type.
func (v Value) SetMapIndex(key, elem Value) {
/* TODO(xsw):
v.mustBe(Map)
v.mustBeExported()
key.mustBeExported()
tt := (*mapType)(unsafe.Pointer(v.typ()))
if (tt.Key == stringType || key.kind() == String) && tt.Key == key.typ() && tt.Elem.Size() <= maxValSize {
k := *(*string)(key.ptr)
if elem.typ() == nil {
mapdelete_faststr(v.typ(), v.pointer(), k)
return
}
elem.mustBeExported()
elem = elem.assignTo("reflect.Value.SetMapIndex", tt.Elem, nil)
var e unsafe.Pointer
if elem.flag&flagIndir != 0 {
e = elem.ptr
} else {
e = unsafe.Pointer(&elem.ptr)
}
mapassign_faststr(v.typ(), v.pointer(), k, e)
return
}
key = key.assignTo("reflect.Value.SetMapIndex", tt.Key, nil)
var k unsafe.Pointer
if key.flag&flagIndir != 0 {
k = key.ptr
} else {
k = unsafe.Pointer(&key.ptr)
}
if elem.typ() == nil {
mapdelete(v.typ(), v.pointer(), k)
return
}
elem.mustBeExported()
elem = elem.assignTo("reflect.Value.SetMapIndex", tt.Elem, nil)
var e unsafe.Pointer
if elem.flag&flagIndir != 0 {
e = elem.ptr
} else {
e = unsafe.Pointer(&elem.ptr)
}
mapassign(v.typ(), v.pointer(), k, e)
*/
panic("todo: reflect.Value.SetMapIndex")
}
// SetUint sets v's underlying value to x.
// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64, or if CanSet() is false.
func (v Value) SetUint(x uint64) {
v.mustBeAssignable()
switch k := v.kind(); k {
default:
panic(&ValueError{"reflect.Value.SetUint", v.kind()})
case Uint:
*(*uint)(v.ptr) = uint(x)
case Uint8:
*(*uint8)(v.ptr) = uint8(x)
case Uint16:
*(*uint16)(v.ptr) = uint16(x)
case Uint32:
*(*uint32)(v.ptr) = uint32(x)
case Uint64:
*(*uint64)(v.ptr) = x
case Uintptr:
*(*uintptr)(v.ptr) = uintptr(x)
}
}
// SetPointer sets the [unsafe.Pointer] value v to x.
// It panics if v's Kind is not UnsafePointer.
func (v Value) SetPointer(x unsafe.Pointer) {
v.mustBeAssignable()
v.mustBe(UnsafePointer)
*(*unsafe.Pointer)(v.ptr) = x
}
// SetString sets v's underlying value to x.
// It panics if v's Kind is not String or if CanSet() is false.
func (v Value) SetString(x string) {
v.mustBeAssignable()
v.mustBe(String)
*(*string)(v.ptr) = x
}
// Slice returns v[i:j].
// It panics if v's Kind is not Array, Slice or String, or if v is an unaddressable array,
// or if the indexes are out of bounds.
func (v Value) Slice(i, j int) Value {
/* TODO(xsw):
var (
cap int
typ *sliceType
base unsafe.Pointer
)
switch kind := v.kind(); kind {
default:
panic(&ValueError{"reflect.Value.Slice", v.kind()})
case Array:
if v.flag&flagAddr == 0 {
panic("reflect.Value.Slice: slice of unaddressable array")
}
tt := (*arrayType)(unsafe.Pointer(v.typ()))
cap = int(tt.Len)
typ = (*sliceType)(unsafe.Pointer(tt.Slice))
base = v.ptr
case Slice:
typ = (*sliceType)(unsafe.Pointer(v.typ()))
s := (*unsafeheader.Slice)(v.ptr)
base = s.Data
cap = s.Cap
case String:
s := (*unsafeheader.String)(v.ptr)
if i < 0 || j < i || j > s.Len {
panic("reflect.Value.Slice: string slice index out of bounds")
}
var t unsafeheader.String
if i < s.Len {
t = unsafeheader.String{Data: arrayAt(s.Data, i, 1, "i < s.Len"), Len: j - i}
}
return Value{v.typ(), unsafe.Pointer(&t), v.flag}
}
if i < 0 || j < i || j > cap {
panic("reflect.Value.Slice: slice index out of bounds")
}
// Declare slice so that gc can see the base pointer in it.
var x []unsafe.Pointer
// Reinterpret as *unsafeheader.Slice to edit.
s := (*unsafeheader.Slice)(unsafe.Pointer(&x))
s.Len = j - i
s.Cap = cap - i
if cap-i > 0 {
s.Data = arrayAt(base, i, typ.Elem.Size(), "i < cap")
} else {
// do not advance pointer, to avoid pointing beyond end of slice
s.Data = base
}
fl := v.flag.ro() | flagIndir | flag(Slice)
return Value{typ.Common(), unsafe.Pointer(&x), fl}
*/
panic("todo: reflect.Value.Slice")
}
// Slice3 is the 3-index form of the slice operation: it returns v[i:j:k].
// It panics if v's Kind is not Array or Slice, or if v is an unaddressable array,
// or if the indexes are out of bounds.
func (v Value) Slice3(i, j, k int) Value {
/* TODO(xsw):
var (
cap int
typ *sliceType
base unsafe.Pointer
)
switch kind := v.kind(); kind {
default:
panic(&ValueError{"reflect.Value.Slice3", v.kind()})
case Array:
if v.flag&flagAddr == 0 {
panic("reflect.Value.Slice3: slice of unaddressable array")
}
tt := (*arrayType)(unsafe.Pointer(v.typ()))
cap = int(tt.Len)
typ = (*sliceType)(unsafe.Pointer(tt.Slice))
base = v.ptr
case Slice:
typ = (*sliceType)(unsafe.Pointer(v.typ()))
s := (*unsafeheader.Slice)(v.ptr)
base = s.Data
cap = s.Cap
}
if i < 0 || j < i || k < j || k > cap {
panic("reflect.Value.Slice3: slice index out of bounds")
}
// Declare slice so that the garbage collector
// can see the base pointer in it.
var x []unsafe.Pointer
// Reinterpret as *unsafeheader.Slice to edit.
s := (*unsafeheader.Slice)(unsafe.Pointer(&x))
s.Len = j - i
s.Cap = k - i
if k-i > 0 {
s.Data = arrayAt(base, i, typ.Elem.Size(), "i < k <= cap")
} else {
// do not advance pointer, to avoid pointing beyond end of slice
s.Data = base
}
fl := v.flag.ro() | flagIndir | flag(Slice)
return Value{typ.Common(), unsafe.Pointer(&x), fl}
*/
panic("todo: reflect.Value.Slice3")
}
// String returns the string v's underlying value, as a string.
// String is a special case because of Go's String method convention.
// Unlike the other getters, it does not panic if v's Kind is not String.
// Instead, it returns a string of the form "<T value>" where T is v's type.
// The fmt package treats Values specially. It does not call their String
// method implicitly but instead prints the concrete values they hold.
func (v Value) String() string {
// stringNonString is split out to keep String inlineable for string kinds.
if v.kind() == String {
return *(*string)(v.ptr)
}
return v.stringNonString()
}
func (v Value) stringNonString() string {
if v.kind() == Invalid {
return "<invalid Value>"
}
// If you call String on a reflect.Value of other type, it's better to
// print something than to panic. Useful in debugging.
return "<" + v.Type().String() + " Value>"
}
// TryRecv attempts to receive a value from the channel v but will not block.
// It panics if v's Kind is not Chan.
// If the receive delivers a value, x is the transferred value and ok is true.
// If the receive cannot finish without blocking, x is the zero Value and ok is false.
// If the channel is closed, x is the zero value for the channel's element type and ok is false.
func (v Value) TryRecv() (x Value, ok bool) {
/* TODO(xsw):
v.mustBe(Chan)
v.mustBeExported()
return v.recv(true)
*/
panic("todo: reflect.Value.TryRecv")
}
// TrySend attempts to send x on the channel v but will not block.
// It panics if v's Kind is not Chan.
// It reports whether the value was sent.
// As in Go, x's value must be assignable to the channel's element type.
func (v Value) TrySend(x Value) bool {
/* TODO(xsw):
v.mustBe(Chan)
v.mustBeExported()
return v.send(x, true)
*/
panic("todo: reflect.Value.TrySend")
}
// Type returns v's type.
func (v Value) Type() Type {
if v.flag != 0 && v.flag&flagMethod == 0 {
return (*rtype)(unsafe.Pointer(v.typ_)) // inline of toRType(v.typ()), for own inlining in inline test
}
return v.typeSlow()
}
func (v Value) typeSlow() Type {
/* TODO(xsw):
if v.flag == 0 {
panic(&ValueError{"reflect.Value.Type", Invalid})
}
typ := v.typ()
if v.flag&flagMethod == 0 {
return toRType(v.typ())
}
// Method value.
// v.typ describes the receiver, not the method type.
i := int(v.flag) >> flagMethodShift
if v.typ().Kind() == abi.Interface {
// Method on interface.
tt := (*interfaceType)(unsafe.Pointer(typ))
if uint(i) >= uint(len(tt.Methods)) {
panic("reflect: internal error: invalid method index")
}
m := &tt.Methods[i]
return toRType(typeOffFor(typ, m.Typ))
}
// Method on concrete type.
ms := typ.ExportedMethods()
if uint(i) >= uint(len(ms)) {
panic("reflect: internal error: invalid method index")
}
m := ms[i]
return toRType(typeOffFor(typ, m.Mtyp))
*/
panic("todo: reflect.Value.Type")
}
// CanUint reports whether Uint can be used without panicking.
func (v Value) CanUint() bool {
switch v.kind() {
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
return true
default:
return false
}
}
// Uint returns v's underlying value, as a uint64.
// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
func (v Value) Uint() uint64 {
k := v.kind()
p := v.ptr
switch k {
case Uint:
return uint64(*(*uint)(p))
case Uint8:
return uint64(*(*uint8)(p))
case Uint16:
return uint64(*(*uint16)(p))
case Uint32:
return uint64(*(*uint32)(p))
case Uint64:
return *(*uint64)(p)
case Uintptr:
return uint64(*(*uintptr)(p))
}
panic(&ValueError{"reflect.Value.Uint", v.kind()})
}
//go:nocheckptr
// This prevents inlining Value.UnsafeAddr when -d=checkptr is enabled,
// which ensures cmd/compile can recognize unsafe.Pointer(v.UnsafeAddr())
// and make an exception.
// UnsafeAddr returns a pointer to v's data, as a uintptr.
// It panics if v is not addressable.
//
// It's preferred to use uintptr(Value.Addr().UnsafePointer()) to get the equivalent result.
func (v Value) UnsafeAddr() uintptr {
if v.typ() == nil {
panic(&ValueError{"reflect.Value.UnsafeAddr", Invalid})
}
if v.flag&flagAddr == 0 {
panic("reflect.Value.UnsafeAddr of unaddressable value")
}
return uintptr(v.ptr)
}
// UnsafePointer returns v's value as a [unsafe.Pointer].
// It panics if v's Kind is not Chan, Func, Map, Pointer, Slice, or UnsafePointer.
//
// If v's Kind is Func, the returned pointer is an underlying
// code pointer, but not necessarily enough to identify a
// single function uniquely. The only guarantee is that the
// result is zero if and only if v is a nil func Value.
//
// If v's Kind is Slice, the returned pointer is to the first
// element of the slice. If the slice is nil the returned value
// is nil. If the slice is empty but non-nil the return value is non-nil.
func (v Value) UnsafePointer() unsafe.Pointer {
/* TODO(xsw):
k := v.kind()
switch k {
case Pointer:
if v.typ().PtrBytes == 0 {
// Since it is a not-in-heap pointer, all pointers to the heap are
// forbidden! See comment in Value.Elem and issue #48399.
if !verifyNotInHeapPtr(*(*uintptr)(v.ptr)) {
panic("reflect: reflect.Value.UnsafePointer on an invalid notinheap pointer")
}
return *(*unsafe.Pointer)(v.ptr)
}
fallthrough
case Chan, Map, UnsafePointer:
return v.pointer()
case Func:
if v.flag&flagMethod != 0 {
// As the doc comment says, the returned pointer is an
// underlying code pointer but not necessarily enough to
// identify a single function uniquely. All method expressions
// created via reflect have the same underlying code pointer,
// so their Pointers are equal. The function used here must
// match the one used in makeMethodValue.
code := methodValueCallCodePtr()
return *(*unsafe.Pointer)(unsafe.Pointer(&code))
}
p := v.pointer()
// Non-nil func value points at data block.
// First word of data block is actual code.
if p != nil {
p = *(*unsafe.Pointer)(p)
}
return p
case Slice:
return (*unsafeheader.Slice)(v.ptr).Data
}
panic(&ValueError{"reflect.Value.UnsafePointer", v.kind()})
*/
panic("todo: reflect.Value.UnsafePointer")
}
//go:linkname unsafe_New github.com/goplus/llgo/internal/runtime.New
func unsafe_New(*abi.Type) unsafe.Pointer