Skip to content

Commit f78bdc8

Browse files
committed
compiler,reflect: add support for [...]T -> []T in reflect
1 parent 4b0c1e3 commit f78bdc8

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

compiler/interface.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
205205
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
206206
types.NewVar(token.NoPos, nil, "elementType", types.Typ[types.UnsafePointer]),
207207
types.NewVar(token.NoPos, nil, "length", types.Typ[types.Uintptr]),
208+
types.NewVar(token.NoPos, nil, "sliceOf", types.Typ[types.UnsafePointer]),
208209
)
209210
case *types.Map:
210211
typeFieldTypes = append(typeFieldTypes,
@@ -303,6 +304,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
303304
c.getTypeCode(types.NewPointer(typ)), // ptrTo
304305
c.getTypeCode(typ.Elem()), // elementType
305306
llvm.ConstInt(c.uintptrType, uint64(typ.Len()), false), // length
307+
c.getTypeCode(types.NewSlice(typ.Elem())), // slicePtr
306308
}
307309
case *types.Map:
308310
typeFields = []llvm.Value{

src/reflect/type.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
// ptrTo *typeStruct
3030
// elem *typeStruct // element type of the array
3131
// arrayLen uintptr // length of the array (this is part of the type)
32+
// slicePtr *typeStruct // pointer to []T type
3233
// - map types (this is still missing the key and element types)
3334
// meta uint8
3435
// nmethods uint16 (0)
@@ -425,6 +426,7 @@ type arrayType struct {
425426
ptrTo *rawType
426427
elem *rawType
427428
arrayLen uintptr
429+
slicePtr *rawType
428430
}
429431

430432
type mapType struct {

src/reflect/value.go

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -555,8 +555,26 @@ func (v Value) Slice(i, j int) Value {
555555
}
556556

557557
case Array:
558-
// TODO(dgryski): can't do this yet because the resulting value needs type slice of v.elem(), not array of v.elem().
559-
// need to be able to look up this "new" type so pointer equality of types still works
558+
v.checkAddressable()
559+
buf, length := buflen(v)
560+
i, j := uintptr(i), uintptr(j)
561+
if j < i || length < j {
562+
slicePanic()
563+
}
564+
565+
elemSize := v.typecode.underlying().elem().Size()
566+
567+
var hdr sliceHeader
568+
hdr.len = j - i
569+
hdr.cap = length - i
570+
hdr.data = unsafe.Add(buf, i*elemSize)
571+
572+
sliceType := (*arrayType)(unsafe.Pointer(v.typecode.underlying())).slicePtr
573+
return Value{
574+
typecode: sliceType,
575+
value: unsafe.Pointer(&hdr),
576+
flags: v.flags,
577+
}
560578

561579
case String:
562580
i, j := uintptr(i), uintptr(j)
@@ -604,9 +622,26 @@ func (v Value) Slice3(i, j, k int) Value {
604622
}
605623

606624
case Array:
607-
// TODO(dgryski): can't do this yet because the resulting value needs type v.elem(), not array of v.elem().
608-
// need to be able to look up this "new" type so pointer equality of types still works
625+
v.checkAddressable()
626+
buf, length := buflen(v)
627+
i, j, k := uintptr(i), uintptr(j), uintptr(k)
628+
if j < i || k < j || length < k {
629+
slicePanic()
630+
}
609631

632+
elemSize := v.typecode.underlying().elem().Size()
633+
634+
var hdr sliceHeader
635+
hdr.len = j - i
636+
hdr.cap = k - i
637+
hdr.data = unsafe.Add(buf, i*elemSize)
638+
639+
sliceType := (*arrayType)(unsafe.Pointer(v.typecode.underlying())).slicePtr
640+
return Value{
641+
typecode: sliceType,
642+
value: unsafe.Pointer(&hdr),
643+
flags: v.flags,
644+
}
610645
}
611646

612647
panic("unimplemented: (reflect.Value).Slice3()")

0 commit comments

Comments
 (0)