diff --git a/compiler/interface.go b/compiler/interface.go index 81234b0c..116ad667 100644 --- a/compiler/interface.go +++ b/compiler/interface.go @@ -218,6 +218,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]), types.NewVar(token.NoPos, nil, "elementType", types.Typ[types.UnsafePointer]), types.NewVar(token.NoPos, nil, "length", types.Typ[types.Uintptr]), + types.NewVar(token.NoPos, nil, "sliceOf", types.Typ[types.UnsafePointer]), ) case *types.Map: typeFieldTypes = append(typeFieldTypes, @@ -326,6 +327,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { c.getTypeCode(types.NewPointer(typ)), // ptrTo c.getTypeCode(typ.Elem()), // elementType llvm.ConstInt(c.uintptrType, uint64(typ.Len()), false), // length + c.getTypeCode(types.NewSlice(typ.Elem())), // slicePtr } case *types.Map: typeFields = []llvm.Value{ diff --git a/src/reflect/type.go b/src/reflect/type.go index bd717af0..39659cc6 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -29,6 +29,7 @@ // ptrTo *typeStruct // elem *typeStruct // element type of the array // arrayLen uintptr // length of the array (this is part of the type) +// slicePtr *typeStruct // pointer to []T type // - map types (this is still missing the key and element types) // meta uint8 // nmethods uint16 (0) @@ -427,6 +428,7 @@ type arrayType struct { ptrTo *rawType elem *rawType arrayLen uintptr + slicePtr *rawType } type mapType struct { diff --git a/src/reflect/value.go b/src/reflect/value.go index 2499fca7..dc81fe66 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -555,8 +555,26 @@ func (v Value) Slice(i, j int) Value { } case Array: - // TODO(dgryski): can't do this yet because the resulting value needs type slice of v.elem(), not array of v.elem(). - // need to be able to look up this "new" type so pointer equality of types still works + v.checkAddressable() + buf, length := buflen(v) + i, j := uintptr(i), uintptr(j) + if j < i || length < j { + slicePanic() + } + + elemSize := v.typecode.underlying().elem().Size() + + var hdr sliceHeader + hdr.len = j - i + hdr.cap = length - i + hdr.data = unsafe.Add(buf, i*elemSize) + + sliceType := (*arrayType)(unsafe.Pointer(v.typecode.underlying())).slicePtr + return Value{ + typecode: sliceType, + value: unsafe.Pointer(&hdr), + flags: v.flags, + } case String: i, j := uintptr(i), uintptr(j) @@ -604,9 +622,26 @@ func (v Value) Slice3(i, j, k int) Value { } case Array: - // TODO(dgryski): can't do this yet because the resulting value needs type v.elem(), not array of v.elem(). - // need to be able to look up this "new" type so pointer equality of types still works + v.checkAddressable() + buf, length := buflen(v) + i, j, k := uintptr(i), uintptr(j), uintptr(k) + if j < i || k < j || length < k { + slicePanic() + } + elemSize := v.typecode.underlying().elem().Size() + + var hdr sliceHeader + hdr.len = j - i + hdr.cap = k - i + hdr.data = unsafe.Add(buf, i*elemSize) + + sliceType := (*arrayType)(unsafe.Pointer(v.typecode.underlying())).slicePtr + return Value{ + typecode: sliceType, + value: unsafe.Pointer(&hdr), + flags: v.flags, + } } panic("unimplemented: (reflect.Value).Slice3()")