internal/lib/reflect: convertOp

This commit is contained in:
visualfc
2024-12-12 16:29:17 +08:00
parent faef4fffab
commit c90b93c1b7
7 changed files with 420 additions and 15 deletions

View File

@@ -15,3 +15,15 @@ float llgoToFloat32(long v) {
k.v = v; k.v = v;
return k.f; return k.f;
} }
long llgoFromFloat64(double v) {
castUnion k;
k.d = v;
return k.v;
}
long llgoFromFloat32(float v) {
castUnion k;
k.f = v;
return k.v;
}

View File

@@ -28,3 +28,9 @@ func ToFloat64(v uintptr) float64
//go:linkname ToFloat32 C.llgoToFloat32 //go:linkname ToFloat32 C.llgoToFloat32
func ToFloat32(v uintptr) float32 func ToFloat32(v uintptr) float32
//go:linkname FromFloat64 C.llgoFromFloat64
func FromFloat64(v float64) uintptr
//go:linkname FromFloat32 C.llgoFromFloat32
func FromFloat32(v float32) uintptr

View File

@@ -90,7 +90,7 @@ _llgo_0:
%13 = call %"github.com/goplus/llgo/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %11) %13 = call %"github.com/goplus/llgo/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %11)
%14 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %13) %14 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %13)
%15 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %13, 0 %15 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %13, 0
%16 = getelementptr ptr, ptr %15, i64 37 %16 = getelementptr ptr, ptr %15, i64 31
%17 = load ptr, ptr %16, align 8 %17 = load ptr, ptr %16, align 8
%18 = insertvalue { ptr, ptr } undef, ptr %17, 0 %18 = insertvalue { ptr, ptr } undef, ptr %17, 0
%19 = insertvalue { ptr, ptr } %18, ptr %14, 1 %19 = insertvalue { ptr, ptr } %18, ptr %14, 1
@@ -185,7 +185,7 @@ _llgo_0:
%6 = call %"github.com/goplus/llgo/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %4) %6 = call %"github.com/goplus/llgo/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %4)
%7 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %6) %7 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %6)
%8 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %6, 0 %8 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %6, 0
%9 = getelementptr ptr, ptr %8, i64 37 %9 = getelementptr ptr, ptr %8, i64 31
%10 = load ptr, ptr %9, align 8 %10 = load ptr, ptr %9, align 8
%11 = insertvalue { ptr, ptr } undef, ptr %10, 0 %11 = insertvalue { ptr, ptr } undef, ptr %10, 0
%12 = insertvalue { ptr, ptr } %11, ptr %7, 1 %12 = insertvalue { ptr, ptr } %11, ptr %7, 1
@@ -286,7 +286,7 @@ _llgo_0:
%16 = call %"github.com/goplus/llgo/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %14) %16 = call %"github.com/goplus/llgo/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %14)
%17 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %16) %17 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %16)
%18 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %16, 0 %18 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %16, 0
%19 = getelementptr ptr, ptr %18, i64 37 %19 = getelementptr ptr, ptr %18, i64 31
%20 = load ptr, ptr %19, align 8 %20 = load ptr, ptr %19, align 8
%21 = insertvalue { ptr, ptr } undef, ptr %20, 0 %21 = insertvalue { ptr, ptr } undef, ptr %20, 0
%22 = insertvalue { ptr, ptr } %21, ptr %17, 1 %22 = insertvalue { ptr, ptr } %21, ptr %17, 1
@@ -393,7 +393,7 @@ _llgo_0:
%8 = call %"github.com/goplus/llgo/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %6) %8 = call %"github.com/goplus/llgo/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %6)
%9 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %8) %9 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %8)
%10 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %8, 0 %10 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %8, 0
%11 = getelementptr ptr, ptr %10, i64 37 %11 = getelementptr ptr, ptr %10, i64 31
%12 = load ptr, ptr %11, align 8 %12 = load ptr, ptr %11, align 8
%13 = insertvalue { ptr, ptr } undef, ptr %12, 0 %13 = insertvalue { ptr, ptr } undef, ptr %12, 0
%14 = insertvalue { ptr, ptr } %13, ptr %9, 1 %14 = insertvalue { ptr, ptr } %13, ptr %9, 1
@@ -827,7 +827,7 @@ _llgo_9: ; preds = %_llgo_8, %_llgo_7
%60 = call %"github.com/goplus/llgo/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %11) %60 = call %"github.com/goplus/llgo/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %11)
%61 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %60) %61 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %60)
%62 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %60, 0 %62 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %60, 0
%63 = getelementptr ptr, ptr %62, i64 20 %63 = getelementptr ptr, ptr %62, i64 18
%64 = load ptr, ptr %63, align 8 %64 = load ptr, ptr %63, align 8
%65 = insertvalue { ptr, ptr } undef, ptr %64, 0 %65 = insertvalue { ptr, ptr } undef, ptr %64, 0
%66 = insertvalue { ptr, ptr } %65, ptr %61, 1 %66 = insertvalue { ptr, ptr } %65, ptr %61, 1
@@ -839,7 +839,7 @@ _llgo_9: ; preds = %_llgo_8, %_llgo_7
%72 = call %"github.com/goplus/llgo/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %11) %72 = call %"github.com/goplus/llgo/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %11)
%73 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %72) %73 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %72)
%74 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %72, 0 %74 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %72, 0
%75 = getelementptr ptr, ptr %74, i64 11 %75 = getelementptr ptr, ptr %74, i64 9
%76 = load ptr, ptr %75, align 8 %76 = load ptr, ptr %75, align 8
%77 = insertvalue { ptr, ptr } undef, ptr %76, 0 %77 = insertvalue { ptr, ptr } undef, ptr %76, 0
%78 = insertvalue { ptr, ptr } %77, ptr %73, 1 %78 = insertvalue { ptr, ptr } %77, ptr %73, 1
@@ -1009,7 +1009,7 @@ _llgo_9: ; preds = %_llgo_8, %_llgo_7
%77 = call %"github.com/goplus/llgo/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %10) %77 = call %"github.com/goplus/llgo/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %10)
%78 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %77) %78 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %77)
%79 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %77, 0 %79 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %77, 0
%80 = getelementptr ptr, ptr %79, i64 20 %80 = getelementptr ptr, ptr %79, i64 18
%81 = load ptr, ptr %80, align 8 %81 = load ptr, ptr %80, align 8
%82 = insertvalue { ptr, ptr } undef, ptr %81, 0 %82 = insertvalue { ptr, ptr } undef, ptr %81, 0
%83 = insertvalue { ptr, ptr } %82, ptr %78, 1 %83 = insertvalue { ptr, ptr } %82, ptr %78, 1
@@ -1021,7 +1021,7 @@ _llgo_9: ; preds = %_llgo_8, %_llgo_7
%89 = call %"github.com/goplus/llgo/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %10) %89 = call %"github.com/goplus/llgo/runtime/internal/runtime.iface" @reflect.Value.Type(%reflect.Value %10)
%90 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %89) %90 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %89)
%91 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %89, 0 %91 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %89, 0
%92 = getelementptr ptr, ptr %91, i64 11 %92 = getelementptr ptr, ptr %91, i64 9
%93 = load ptr, ptr %92, align 8 %93 = load ptr, ptr %92, align 8
%94 = insertvalue { ptr, ptr } undef, ptr %93, 0 %94 = insertvalue { ptr, ptr } undef, ptr %93, 0
%95 = insertvalue { ptr, ptr } %94, ptr %90, 1 %95 = insertvalue { ptr, ptr } %94, ptr %90, 1

View File

@@ -15,3 +15,15 @@ float llgoToFloat32(long v) {
k.v = v; k.v = v;
return k.f; return k.f;
} }
long llgoFromFloat64(double v) {
castUnion k;
k.d = v;
return k.v;
}
long llgoFromFloat32(float v) {
castUnion k;
k.f = v;
return k.v;
}

View File

@@ -28,3 +28,9 @@ func ToFloat64(v uintptr) float64
//go:linkname ToFloat32 C.llgoToFloat32 //go:linkname ToFloat32 C.llgoToFloat32
func ToFloat32(v uintptr) float32 func ToFloat32(v uintptr) float32
//go:linkname FromFloat64 C.llgoFromFloat64
func FromFloat64(v float64) uintptr
//go:linkname FromFloat32 C.llgoFromFloat32
func FromFloat32(v float32) uintptr

View File

@@ -924,13 +924,10 @@ func (t *rtype) AssignableTo(u Type) bool {
} }
func (t *rtype) ConvertibleTo(u Type) bool { func (t *rtype) ConvertibleTo(u Type) bool {
/* if u == nil {
if u == nil { panic("reflect: nil type passed to Type.ConvertibleTo")
panic("reflect: nil type passed to Type.ConvertibleTo") }
} return convertOp(u.common(), t.common()) != nil
return convertOp(u.common(), t.common()) != nil
*/
panic("todo: reflect.rtype.ConvertibleTo")
} }
func (t *rtype) Comparable() bool { func (t *rtype) Comparable() bool {

View File

@@ -28,6 +28,7 @@ import (
"github.com/goplus/llgo/runtime/abi" "github.com/goplus/llgo/runtime/abi"
"github.com/goplus/llgo/runtime/internal/clite/bitcast" "github.com/goplus/llgo/runtime/internal/clite/bitcast"
"github.com/goplus/llgo/runtime/internal/ffi" "github.com/goplus/llgo/runtime/internal/ffi"
"github.com/goplus/llgo/runtime/internal/lib/internal/itoa"
"github.com/goplus/llgo/runtime/internal/runtime" "github.com/goplus/llgo/runtime/internal/runtime"
"github.com/goplus/llgo/runtime/internal/runtime/goarch" "github.com/goplus/llgo/runtime/internal/runtime/goarch"
) )
@@ -1856,6 +1857,43 @@ func (v Value) assignTo(context string, dst *abi.Type, target unsafe.Pointer) Va
panic(context + ": value of type " + stringFor(v.typ()) + " is not assignable to type " + stringFor(dst)) panic(context + ": value of type " + stringFor(v.typ()) + " is not assignable to type " + stringFor(dst))
} }
// Convert returns the value v converted to type t.
// If the usual Go conversion rules do not allow conversion
// of the value v to type t, or if converting v to type t panics, Convert panics.
func (v Value) Convert(t Type) Value {
if v.flag&flagMethod != 0 {
v = makeMethodValue("Convert", v)
}
op := convertOp(t.common(), v.typ())
if op == nil {
panic("reflect.Value.Convert: value of type " + stringFor(v.typ()) + " cannot be converted to type " + t.String())
}
return op(v, t)
}
// CanConvert reports whether the value v can be converted to type t.
// If v.CanConvert(t) returns true then v.Convert(t) will not panic.
func (v Value) CanConvert(t Type) bool {
vt := v.Type()
if !vt.ConvertibleTo(t) {
return false
}
// Converting from slice to array or to pointer-to-array can panic
// depending on the value.
switch {
case vt.Kind() == Slice && t.Kind() == Array:
if t.Len() > v.Len() {
return false
}
case vt.Kind() == Slice && t.Kind() == Pointer && t.Elem().Kind() == Array:
n := t.Elem().Len()
if n > v.Len() {
return false
}
}
return true
}
// memmove copies size bytes to dst from src. No write barriers are used. // memmove copies size bytes to dst from src. No write barriers are used.
// //
//go:linkname memmove C.memmove //go:linkname memmove C.memmove
@@ -2581,6 +2619,340 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype *abi.Type, t
return return
} }
// convertOp returns the function to convert a value of type src
// to a value of type dst. If the conversion is illegal, convertOp returns nil.
func convertOp(dst, src *abi.Type) func(Value, Type) Value {
switch Kind(src.Kind()) {
case Int, Int8, Int16, Int32, Int64:
switch Kind(dst.Kind()) {
case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
return cvtInt
case Float32, Float64:
return cvtIntFloat
case String:
return cvtIntString
}
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
switch Kind(dst.Kind()) {
case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
return cvtUint
case Float32, Float64:
return cvtUintFloat
case String:
return cvtUintString
}
case Float32, Float64:
switch Kind(dst.Kind()) {
case Int, Int8, Int16, Int32, Int64:
return cvtFloatInt
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
return cvtFloatUint
case Float32, Float64:
return cvtFloat
}
case Complex64, Complex128:
switch Kind(dst.Kind()) {
case Complex64, Complex128:
return cvtComplex
}
case String:
if dst.Kind() == abi.Slice && pkgPathFor(dst.Elem()) == "" {
switch Kind(dst.Elem().Kind()) {
case Uint8:
return cvtStringBytes
case Int32:
return cvtStringRunes
}
}
case Slice:
if dst.Kind() == abi.String && pkgPathFor(src.Elem()) == "" {
switch Kind(src.Elem().Kind()) {
case Uint8:
return cvtBytesString
case Int32:
return cvtRunesString
}
}
// "x is a slice, T is a pointer-to-array type,
// and the slice and array types have identical element types."
if dst.Kind() == abi.Pointer && dst.Elem().Kind() == abi.Array && src.Elem() == dst.Elem().Elem() {
return cvtSliceArrayPtr
}
// "x is a slice, T is an array type,
// and the slice and array types have identical element types."
if dst.Kind() == abi.Array && src.Elem() == dst.Elem() {
return cvtSliceArray
}
case Chan:
if dst.Kind() == abi.Chan && specialChannelAssignability(dst, src) {
return cvtDirect
}
}
// dst and src have same underlying type.
if haveIdenticalUnderlyingType(dst, src, false) {
return cvtDirect
}
// dst and src are non-defined pointer types with same underlying base type.
if dst.Kind() == abi.Pointer && nameFor(dst) == "" &&
src.Kind() == abi.Pointer && nameFor(src) == "" &&
haveIdenticalUnderlyingType(elem(dst), elem(src), false) {
return cvtDirect
}
if implements(dst, src) {
if src.Kind() == abi.Interface {
return cvtI2I
}
return cvtT2I
}
return nil
}
// _64bit = true on 64-bit systems, false on 32-bit systems
const is64bit = (1 << (^uintptr(0) >> 63) / 2) == 1
// makeInt returns a Value of type t equal to bits (possibly truncated),
// where t is a signed or unsigned int type.
func makeInt(f flag, bits uint64, t Type) Value {
typ := t.common()
var ptr unsafe.Pointer
switch typ.Size() {
case 1, 2, 4:
ptr = unsafe.Pointer(uintptr(bits))
case 8:
if is64bit {
ptr = unsafe.Pointer(uintptr(bits))
} else {
ptr = unsafe_New(typ)
*(*uint64)(ptr) = bits
f |= flagIndir
}
}
return Value{typ, ptr, f | flag(typ.Kind())}
}
// makeFloat returns a Value of type t equal to v (possibly truncated to float32),
// where t is a float32 or float64 type.
func makeFloat(f flag, v float64, t Type) Value {
typ := t.common()
var ptr unsafe.Pointer
switch typ.Size() {
case 4:
ptr = unsafe.Pointer(bitcast.FromFloat32(float32(v)))
case 8:
if is64bit {
ptr = unsafe.Pointer(bitcast.FromFloat64(v))
} else {
ptr = unsafe_New(typ)
*(*float64)(ptr) = v
f |= flagIndir
}
}
return Value{typ, ptr, f | flag(typ.Kind())}
}
// makeFloat32 returns a Value of type t equal to v, where t is a float32 type.
func makeFloat32(f flag, ptr unsafe.Pointer, t Type) Value {
typ := t.common()
return Value{typ, ptr, f | flag(typ.Kind())}
}
// makeComplex returns a Value of type t equal to v (possibly truncated to complex64),
// where t is a complex64 or complex128 type.
func makeComplex(f flag, v complex128, t Type) Value {
typ := t.common()
ptr := unsafe_New(typ)
switch typ.Size() {
case 8:
*(*complex64)(ptr) = complex64(v)
case 16:
*(*complex128)(ptr) = v
}
return Value{typ, ptr, f | flagIndir | flag(typ.Kind())}
}
func makeString(f flag, v string, t Type) Value {
ret := New(t).Elem()
ret.SetString(v)
ret.flag = ret.flag&^flagAddr | f
return ret
}
func makeBytes(f flag, v []byte, t Type) Value {
ret := New(t).Elem()
ret.SetBytes(v)
ret.flag = ret.flag&^flagAddr | f
return ret
}
func makeRunes(f flag, v []rune, t Type) Value {
ret := New(t).Elem()
ret.setRunes(v)
ret.flag = ret.flag&^flagAddr | f
return ret
}
// These conversion functions are returned by convertOp
// for classes of conversions. For example, the first function, cvtInt,
// takes any value v of signed int type and returns the value converted
// to type t, where t is any signed or unsigned int type.
// convertOp: intXX -> [u]intXX
func cvtInt(v Value, t Type) Value {
return makeInt(v.flag.ro(), uint64(v.Int()), t)
}
// convertOp: uintXX -> [u]intXX
func cvtUint(v Value, t Type) Value {
return makeInt(v.flag.ro(), v.Uint(), t)
}
// convertOp: floatXX -> intXX
func cvtFloatInt(v Value, t Type) Value {
return makeInt(v.flag.ro(), uint64(int64(v.Float())), t)
}
// convertOp: floatXX -> uintXX
func cvtFloatUint(v Value, t Type) Value {
return makeInt(v.flag.ro(), uint64(v.Float()), t)
}
// convertOp: intXX -> floatXX
func cvtIntFloat(v Value, t Type) Value {
return makeFloat(v.flag.ro(), float64(v.Int()), t)
}
// convertOp: uintXX -> floatXX
func cvtUintFloat(v Value, t Type) Value {
return makeFloat(v.flag.ro(), float64(v.Uint()), t)
}
// convertOp: floatXX -> floatXX
func cvtFloat(v Value, t Type) Value {
if v.Type().Kind() == Float32 && t.Kind() == Float32 {
// Don't do any conversion if both types have underlying type float32.
// This avoids converting to float64 and back, which will
// convert a signaling NaN to a quiet NaN. See issue 36400.
return makeFloat32(v.flag.ro(), v.ptr, t)
}
return makeFloat(v.flag.ro(), v.Float(), t)
}
// convertOp: complexXX -> complexXX
func cvtComplex(v Value, t Type) Value {
return makeComplex(v.flag.ro(), v.Complex(), t)
}
// convertOp: intXX -> string
func cvtIntString(v Value, t Type) Value {
s := "\uFFFD"
if x := v.Int(); int64(rune(x)) == x {
s = string(rune(x))
}
return makeString(v.flag.ro(), s, t)
}
// convertOp: uintXX -> string
func cvtUintString(v Value, t Type) Value {
s := "\uFFFD"
if x := v.Uint(); uint64(rune(x)) == x {
s = string(rune(x))
}
return makeString(v.flag.ro(), s, t)
}
// convertOp: []byte -> string
func cvtBytesString(v Value, t Type) Value {
return makeString(v.flag.ro(), string(v.Bytes()), t)
}
// convertOp: string -> []byte
func cvtStringBytes(v Value, t Type) Value {
return makeBytes(v.flag.ro(), []byte(v.String()), t)
}
// convertOp: []rune -> string
func cvtRunesString(v Value, t Type) Value {
return makeString(v.flag.ro(), string(v.runes()), t)
}
// convertOp: string -> []rune
func cvtStringRunes(v Value, t Type) Value {
return makeRunes(v.flag.ro(), []rune(v.String()), t)
}
// convertOp: []T -> *[N]T
func cvtSliceArrayPtr(v Value, t Type) Value {
n := t.Elem().Len()
if n > v.Len() {
panic("reflect: cannot convert slice with length " + itoa.Itoa(v.Len()) + " to pointer to array with length " + itoa.Itoa(n))
}
h := (*unsafeheaderSlice)(v.ptr)
return Value{t.common(), h.Data, v.flag&^(flagIndir|flagAddr|flagKindMask) | flag(Pointer)}
}
// convertOp: []T -> [N]T
func cvtSliceArray(v Value, t Type) Value {
n := t.Len()
if n > v.Len() {
panic("reflect: cannot convert slice with length " + itoa.Itoa(v.Len()) + " to array with length " + itoa.Itoa(n))
}
h := (*unsafeheaderSlice)(v.ptr)
typ := t.common()
ptr := h.Data
c := unsafe_New(typ)
typedmemmove(typ, c, ptr)
ptr = c
return Value{typ, ptr, v.flag&^(flagAddr|flagKindMask) | flag(Array)}
}
// convertOp: direct copy
func cvtDirect(v Value, typ Type) Value {
f := v.flag
t := typ.common()
ptr := v.ptr
if f&flagAddr != 0 {
// indirect, mutable word - make a copy
c := unsafe_New(t)
typedmemmove(t, c, ptr)
ptr = c
f &^= flagAddr
}
return Value{t, ptr, v.flag.ro() | f} // v.flag.ro()|f == f?
}
// convertOp: concrete -> interface
func cvtT2I(v Value, typ Type) Value {
target := unsafe_New(typ.common())
x := valueInterface(v, false)
if typ.NumMethod() == 0 {
*(*any)(target) = x
} else {
ifaceE2I(typ.common(), x, target)
}
return Value{typ.common(), target, v.flag.ro() | flagIndir | flag(Interface)}
}
// convertOp: interface -> interface
func cvtI2I(v Value, typ Type) Value {
if v.IsNil() {
ret := Zero(typ)
ret.flag |= v.flag.ro()
return ret
}
return cvtT2I(v.Elem(), typ)
}
//go:linkname chancap github.com/goplus/llgo/runtime/internal/runtime.ChanCap //go:linkname chancap github.com/goplus/llgo/runtime/internal/runtime.ChanCap
func chancap(ch unsafe.Pointer) int func chancap(ch unsafe.Pointer) int