Skip to content

Commit 43f9907

Browse files
authored
Merge pull request #381 from xushiwei/q
patch reflect: ValueOf/Int
2 parents 7042dd8 + 0e6f5d1 commit 43f9907

File tree

3 files changed

+480
-4
lines changed

3 files changed

+480
-4
lines changed

_demo/rtype/rtype.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,7 @@ func main() {
88

99
v := reflect.Zero(tyIntSlice)
1010
println(v.Len())
11+
12+
v = reflect.ValueOf(100)
13+
println(v.Int())
1114
}

internal/lib/reflect/value.go

Lines changed: 137 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,83 @@ func (f flag) ro() flag {
101101
return 0
102102
}
103103

104+
func (v Value) typ() *abi.Type {
105+
// Types are either static (for compiler-created types) or
106+
// heap-allocated but always reachable (for reflection-created
107+
// types, held in the central map). So there is no need to
108+
// escape types. noescape here help avoid unnecessary escape
109+
// of v.
110+
return (*abi.Type)(unsafe.Pointer(v.typ_))
111+
}
112+
113+
// pointer returns the underlying pointer represented by v.
114+
// v.Kind() must be Pointer, Map, Chan, Func, or UnsafePointer
115+
// if v.Kind() == Pointer, the base type must not be not-in-heap.
116+
func (v Value) pointer() unsafe.Pointer {
117+
/*
118+
if v.typ().Size() != goarch.PtrSize || !v.typ().Pointers() {
119+
panic("can't call pointer on a non-pointer Value")
120+
}
121+
if v.flag&flagIndir != 0 {
122+
return *(*unsafe.Pointer)(v.ptr)
123+
}
124+
return v.ptr
125+
*/
126+
panic("todo")
127+
}
128+
129+
// packEface converts v to the empty interface.
130+
func packEface(v Value) any {
131+
t := v.typ()
132+
var i any
133+
e := (*emptyInterface)(unsafe.Pointer(&i))
134+
// First, fill in the data portion of the interface.
135+
switch {
136+
case t.IfaceIndir():
137+
if v.flag&flagIndir == 0 {
138+
panic("bad indir")
139+
}
140+
// Value is indirect, and so is the interface we're making.
141+
ptr := v.ptr
142+
if v.flag&flagAddr != 0 {
143+
// TODO: pass safe boolean from valueInterface so
144+
// we don't need to copy if safe==true?
145+
c := unsafe_New(t)
146+
typedmemmove(t, c, ptr)
147+
ptr = c
148+
}
149+
e.word = ptr
150+
case v.flag&flagIndir != 0:
151+
// Value is indirect, but interface is direct. We need
152+
// to load the data at v.ptr into the interface data word.
153+
e.word = *(*unsafe.Pointer)(v.ptr)
154+
default:
155+
// Value is direct, and so is the interface.
156+
e.word = v.ptr
157+
}
158+
// Now, fill in the type portion. We're very careful here not
159+
// to have any operation between the e.word and e.typ assignments
160+
// that would let the garbage collector observe the partially-built
161+
// interface value.
162+
e.typ = t
163+
return i
164+
}
165+
166+
// unpackEface converts the empty interface i to a Value.
167+
func unpackEface(i any) Value {
168+
e := (*emptyInterface)(unsafe.Pointer(&i))
169+
// NOTE: don't read e.word until we know whether it is really a pointer or not.
170+
t := e.typ
171+
if t == nil {
172+
return Value{}
173+
}
174+
f := flag(t.Kind())
175+
if t.IfaceIndir() {
176+
f |= flagIndir
177+
}
178+
return Value{t, e.word, f}
179+
}
180+
104181
// A ValueError occurs when a Value method is invoked on
105182
// a Value that does not support it. Such cases are documented
106183
// in the description of each method.
@@ -227,14 +304,17 @@ func (v Value) Int() int64 {
227304
p := v.ptr
228305
switch k {
229306
case Int:
230-
return int64(*(*int)(p))
307+
return int64(uintptr(p))
231308
case Int8:
232-
return int64(*(*int8)(p))
309+
return int64(uintptr(p))
233310
case Int16:
234-
return int64(*(*int16)(p))
311+
return int64(uintptr(p))
235312
case Int32:
236-
return int64(*(*int32)(p))
313+
return int64(uintptr(p))
237314
case Int64:
315+
if unsafe.Sizeof(uintptr(0)) == 8 {
316+
return int64(uintptr(p))
317+
}
238318
return *(*int64)(p)
239319
}
240320
panic(&ValueError{"reflect.Value.Int", v.kind()})
@@ -520,6 +600,16 @@ func unsafe_New(*abi.Type) unsafe.Pointer
520600
//go:linkname unsafe_NewArray github.com/goplus/llgo/internal/runtime.NewArray
521601
func unsafe_NewArray(*abi.Type, int) unsafe.Pointer
522602

603+
// ValueOf returns a new Value initialized to the concrete value
604+
// stored in the interface i. ValueOf(nil) returns the zero Value.
605+
func ValueOf(i any) Value {
606+
if i == nil {
607+
return Value{}
608+
}
609+
610+
return unpackEface(i)
611+
}
612+
523613
// Zero returns a Value representing the zero value for the specified type.
524614
// The result is different from the zero value of the Value struct,
525615
// which represents no value at all.
@@ -546,3 +636,46 @@ func Zero(typ Type) Value {
546636
// TODO(xsw): check this
547637
// must match declarations in runtime/map.go.
548638
const maxZero = runtime.MaxZero
639+
640+
// memmove copies size bytes to dst from src. No write barriers are used.
641+
//
642+
//go:linkname memmove C.memmove
643+
func memmove(dst, src unsafe.Pointer, size uintptr)
644+
645+
// typedmemmove copies a value of type t to dst from src.
646+
//
647+
//go:linkname typedmemmove github.com/goplus/llgo/internal/runtime.Typedmemmove
648+
func typedmemmove(t *abi.Type, dst, src unsafe.Pointer)
649+
650+
/* TODO(xsw):
651+
// typedmemclr zeros the value at ptr of type t.
652+
//
653+
//go:noescape
654+
func typedmemclr(t *abi.Type, ptr unsafe.Pointer)
655+
656+
// typedmemclrpartial is like typedmemclr but assumes that
657+
// dst points off bytes into the value and only clears size bytes.
658+
//
659+
//go:noescape
660+
func typedmemclrpartial(t *abi.Type, ptr unsafe.Pointer, off, size uintptr)
661+
662+
// typedslicecopy copies a slice of elemType values from src to dst,
663+
// returning the number of elements copied.
664+
//
665+
//go:noescape
666+
func typedslicecopy(t *abi.Type, dst, src unsafeheaderSlice) int
667+
668+
// typedarrayclear zeroes the value at ptr of an array of elemType,
669+
// only clears len elem.
670+
//
671+
//go:noescape
672+
func typedarrayclear(elemType *abi.Type, ptr unsafe.Pointer, len int)
673+
674+
//go:noescape
675+
func typehash(t *abi.Type, p unsafe.Pointer, h uintptr) uintptr
676+
677+
func verifyNotInHeapPtr(p uintptr) bool
678+
679+
//go:noescape
680+
func growslice(t *abi.Type, old unsafeheaderSlice, num int) unsafeheaderSlice
681+
*/

0 commit comments

Comments
 (0)