internal/lib/reflect: makeMethodValue
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
package main
|
||||
|
||||
import "reflect"
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func main() {
|
||||
callFunc()
|
||||
@@ -56,6 +59,11 @@ type I interface {
|
||||
Add(n int) int
|
||||
}
|
||||
|
||||
type abi struct {
|
||||
typ unsafe.Pointer
|
||||
data unsafe.Pointer
|
||||
}
|
||||
|
||||
func callMethod() {
|
||||
t := &T{1}
|
||||
v := reflect.ValueOf(t)
|
||||
@@ -63,11 +71,15 @@ func callMethod() {
|
||||
println("method", fn.Kind(), fn.Type().String())
|
||||
r := fn.Call([]reflect.Value{reflect.ValueOf(100)})
|
||||
println(r[0].Int())
|
||||
//TODO type assert
|
||||
// ifn, ok := fn.Interface().(func(int) int)
|
||||
// if !ok {
|
||||
// panic("error")
|
||||
// }
|
||||
// ifn(1)
|
||||
v2 := reflect.ValueOf(fn.Interface())
|
||||
r2 := v2.Call([]reflect.Value{reflect.ValueOf(100)})
|
||||
println(r2[0].Int())
|
||||
}
|
||||
|
||||
func callIMethod() {
|
||||
@@ -77,9 +89,13 @@ func callIMethod() {
|
||||
println("imethod", fn.Kind(), fn.Type().String())
|
||||
r := fn.Call([]reflect.Value{reflect.ValueOf(100)})
|
||||
println(r[0].Int())
|
||||
//TODO type assert
|
||||
// ifn, ok := fn.Interface().(func(int) int)
|
||||
// if !ok {
|
||||
// panic("error")
|
||||
// }
|
||||
// ifn(1)
|
||||
v2 := reflect.ValueOf(fn.Interface())
|
||||
r2 := v2.Call([]reflect.Value{reflect.ValueOf(100)})
|
||||
println(r2[0].Int())
|
||||
}
|
||||
|
||||
@@ -448,6 +448,37 @@ _llgo_0:
|
||||
%55 = call i64 @reflect.Value.Int(%reflect.Value %54)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %55)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||
%56 = call %"github.com/goplus/llgo/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %18)
|
||||
%57 = call %reflect.Value @reflect.ValueOf(%"github.com/goplus/llgo/internal/runtime.eface" %56)
|
||||
%58 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 24)
|
||||
%59 = getelementptr inbounds %reflect.Value, ptr %58, i64 0
|
||||
%60 = load ptr, ptr @_llgo_int, align 8
|
||||
%61 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
|
||||
%62 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %61, i32 0, i32 0
|
||||
store ptr %60, ptr %62, align 8
|
||||
%63 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %61, i32 0, i32 1
|
||||
store ptr inttoptr (i64 100 to ptr), ptr %63, align 8
|
||||
%64 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %61, align 8
|
||||
%65 = call %reflect.Value @reflect.ValueOf(%"github.com/goplus/llgo/internal/runtime.eface" %64)
|
||||
store %reflect.Value %65, ptr %59, align 8
|
||||
%66 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
|
||||
%67 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %66, i32 0, i32 0
|
||||
store ptr %58, ptr %67, align 8
|
||||
%68 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %66, i32 0, i32 1
|
||||
store i64 1, ptr %68, align 4
|
||||
%69 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %66, i32 0, i32 2
|
||||
store i64 1, ptr %69, align 4
|
||||
%70 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %66, align 8
|
||||
%71 = call %"github.com/goplus/llgo/internal/runtime.Slice" @reflect.Value.Call(%reflect.Value %57, %"github.com/goplus/llgo/internal/runtime.Slice" %70)
|
||||
%72 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %71, 0
|
||||
%73 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %71, 1
|
||||
%74 = icmp sge i64 0, %73
|
||||
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %74)
|
||||
%75 = getelementptr inbounds %reflect.Value, ptr %72, i64 0
|
||||
%76 = load %reflect.Value, ptr %75, align 8
|
||||
%77 = call i64 @reflect.Value.Int(%reflect.Value %76)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %77)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||
ret void
|
||||
}
|
||||
|
||||
@@ -521,6 +552,37 @@ _llgo_0:
|
||||
%45 = call i64 @reflect.Value.Int(%reflect.Value %44)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %45)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||
%46 = call %"github.com/goplus/llgo/internal/runtime.eface" @reflect.Value.Interface(%reflect.Value %8)
|
||||
%47 = call %reflect.Value @reflect.ValueOf(%"github.com/goplus/llgo/internal/runtime.eface" %46)
|
||||
%48 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 24)
|
||||
%49 = getelementptr inbounds %reflect.Value, ptr %48, i64 0
|
||||
%50 = load ptr, ptr @_llgo_int, align 8
|
||||
%51 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
|
||||
%52 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %51, i32 0, i32 0
|
||||
store ptr %50, ptr %52, align 8
|
||||
%53 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %51, i32 0, i32 1
|
||||
store ptr inttoptr (i64 100 to ptr), ptr %53, align 8
|
||||
%54 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %51, align 8
|
||||
%55 = call %reflect.Value @reflect.ValueOf(%"github.com/goplus/llgo/internal/runtime.eface" %54)
|
||||
store %reflect.Value %55, ptr %49, align 8
|
||||
%56 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
|
||||
%57 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %56, i32 0, i32 0
|
||||
store ptr %48, ptr %57, align 8
|
||||
%58 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %56, i32 0, i32 1
|
||||
store i64 1, ptr %58, align 4
|
||||
%59 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %56, i32 0, i32 2
|
||||
store i64 1, ptr %59, align 4
|
||||
%60 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %56, align 8
|
||||
%61 = call %"github.com/goplus/llgo/internal/runtime.Slice" @reflect.Value.Call(%reflect.Value %47, %"github.com/goplus/llgo/internal/runtime.Slice" %60)
|
||||
%62 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %61, 0
|
||||
%63 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %61, 1
|
||||
%64 = icmp sge i64 0, %63
|
||||
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %64)
|
||||
%65 = getelementptr inbounds %reflect.Value, ptr %62, i64 0
|
||||
%66 = load %reflect.Value, ptr %65, align 8
|
||||
%67 = call i64 @reflect.Value.Int(%reflect.Value %66)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %67)
|
||||
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,13 @@
|
||||
|
||||
package reflect
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/internal/abi"
|
||||
"github.com/goplus/llgo/internal/runtime"
|
||||
)
|
||||
|
||||
/*
|
||||
import (
|
||||
"unsafe"
|
||||
@@ -111,7 +118,6 @@ type methodValue struct {
|
||||
// reflect can tell, but the true func representation can be handled
|
||||
// by code like Convert and Interface and Assign.
|
||||
func makeMethodValue(op string, v Value) Value {
|
||||
/*
|
||||
if v.flag&flagMethod == 0 {
|
||||
panic("reflect: internal error: invalid use of makeMethodValue")
|
||||
}
|
||||
@@ -122,31 +128,27 @@ func makeMethodValue(op string, v Value) Value {
|
||||
rcvr := Value{v.typ(), v.ptr, fl}
|
||||
|
||||
// v.Type returns the actual type of the method value.
|
||||
ftyp := (*funcType)(unsafe.Pointer(v.Type().(*rtype)))
|
||||
|
||||
code := methodValueCallCodePtr()
|
||||
|
||||
// methodValue contains a stack map for use by the runtime
|
||||
_, _, abid := funcLayout(ftyp, nil)
|
||||
fv := &methodValue{
|
||||
makeFuncCtxt: makeFuncCtxt{
|
||||
fn: code,
|
||||
stack: abid.stackPtrs,
|
||||
argLen: abid.stackCallArgsSize,
|
||||
regPtrs: abid.inRegPtrs,
|
||||
},
|
||||
method: int(v.flag) >> flagMethodShift,
|
||||
rcvr: rcvr,
|
||||
}
|
||||
|
||||
ftyp := *(*funcType)(unsafe.Pointer(v.Type().(*rtype)))
|
||||
ptyp := rtypeOf(unsafe.Pointer(uintptr(0)))
|
||||
ftyp.In = append([]*abi.Type{ptyp}, ftyp.In...)
|
||||
typ := runtime.Struct("", 2*unsafe.Sizeof(0), abi.StructField{
|
||||
Name_: "llgo_ctx",
|
||||
Typ: &ftyp.Type,
|
||||
}, abi.StructField{
|
||||
Name_: "f",
|
||||
Typ: ptyp,
|
||||
Offset: unsafe.Sizeof(0),
|
||||
})
|
||||
typ.TFlag |= abi.TFlagClosure
|
||||
_, _, fn := methodReceiver(op, rcvr, int(v.flag)>>flagMethodShift)
|
||||
fv := &struct {
|
||||
fn unsafe.Pointer
|
||||
env unsafe.Pointer
|
||||
}{fn, v.ptr}
|
||||
// Cause panic if method is not appropriate.
|
||||
// The panic would still happen during the call if we omit this,
|
||||
// but we want Interface() and other operations to fail early.
|
||||
methodReceiver(op, fv.rcvr, fv.method)
|
||||
|
||||
return Value{ftyp.Common(), unsafe.Pointer(fv), v.flag&flagRO | flag(Func)}
|
||||
*/
|
||||
panic("todo: reflect.makeMethodValue")
|
||||
return Value{typ, unsafe.Pointer(fv), v.flag&flagRO | flagIndir | flag(Func)}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user