parent
ea89b2482f
commit
a84dbde7fc
|
@ -901,10 +901,17 @@ go_reflect_makefunc_file = \
|
||||||
go_reflect_makefunc_s_file = \
|
go_reflect_makefunc_s_file = \
|
||||||
go/reflect/makefunc_amd64.S
|
go/reflect/makefunc_amd64.S
|
||||||
else
|
else
|
||||||
|
if LIBGO_IS_386
|
||||||
|
go_reflect_makefunc_file = \
|
||||||
|
go/reflect/makefuncgo_386.go
|
||||||
|
go_reflect_makefunc_s_file = \
|
||||||
|
go/reflect/makefunc_386.S
|
||||||
|
else
|
||||||
go_reflect_makefunc_file =
|
go_reflect_makefunc_file =
|
||||||
go_reflect_makefunc_s_file = \
|
go_reflect_makefunc_s_file = \
|
||||||
go/reflect/makefunc_dummy.c
|
go/reflect/makefunc_dummy.c
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
go_reflect_files = \
|
go_reflect_files = \
|
||||||
go/reflect/deepequal.go \
|
go/reflect/deepequal.go \
|
||||||
|
|
|
@ -1087,12 +1087,18 @@ go_path_files = \
|
||||||
go/path/match.go \
|
go/path/match.go \
|
||||||
go/path/path.go
|
go/path/path.go
|
||||||
|
|
||||||
@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_file =
|
@LIBGO_IS_386_FALSE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_file =
|
||||||
|
@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_file = \
|
||||||
|
@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@ go/reflect/makefuncgo_386.go
|
||||||
|
|
||||||
@LIBGO_IS_X86_64_TRUE@go_reflect_makefunc_file = \
|
@LIBGO_IS_X86_64_TRUE@go_reflect_makefunc_file = \
|
||||||
@LIBGO_IS_X86_64_TRUE@ go/reflect/makefuncgo_amd64.go
|
@LIBGO_IS_X86_64_TRUE@ go/reflect/makefuncgo_amd64.go
|
||||||
|
|
||||||
@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_s_file = \
|
@LIBGO_IS_386_FALSE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_s_file = \
|
||||||
@LIBGO_IS_X86_64_FALSE@ go/reflect/makefunc_dummy.c
|
@LIBGO_IS_386_FALSE@@LIBGO_IS_X86_64_FALSE@ go/reflect/makefunc_dummy.c
|
||||||
|
|
||||||
|
@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_s_file = \
|
||||||
|
@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@ go/reflect/makefunc_386.S
|
||||||
|
|
||||||
@LIBGO_IS_X86_64_TRUE@go_reflect_makefunc_s_file = \
|
@LIBGO_IS_X86_64_TRUE@go_reflect_makefunc_s_file = \
|
||||||
@LIBGO_IS_X86_64_TRUE@ go/reflect/makefunc_amd64.S
|
@LIBGO_IS_X86_64_TRUE@ go/reflect/makefunc_amd64.S
|
||||||
|
|
|
@ -1432,7 +1432,7 @@ func TestFunc(t *testing.T) {
|
||||||
|
|
||||||
func TestMakeFunc(t *testing.T) {
|
func TestMakeFunc(t *testing.T) {
|
||||||
switch runtime.GOARCH {
|
switch runtime.GOARCH {
|
||||||
case "amd64":
|
case "amd64", "386":
|
||||||
default:
|
default:
|
||||||
t.Skip("MakeFunc not implemented for " + runtime.GOARCH)
|
t.Skip("MakeFunc not implemented for " + runtime.GOARCH)
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch runtime.GOARCH {
|
switch runtime.GOARCH {
|
||||||
case "amd64":
|
case "amd64", "386":
|
||||||
default:
|
default:
|
||||||
panic("reflect.MakeFunc not implemented for " + runtime.GOARCH)
|
panic("reflect.MakeFunc not implemented for " + runtime.GOARCH)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
# Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style
|
||||||
|
# license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
# MakeFunc 386 assembly code.
|
||||||
|
|
||||||
|
.global reflect.makeFuncStub
|
||||||
|
|
||||||
|
#ifdef __ELF__
|
||||||
|
.type reflect.makeFuncStub,@function
|
||||||
|
#endif
|
||||||
|
|
||||||
|
reflect.makeFuncStub:
|
||||||
|
.cfi_startproc
|
||||||
|
|
||||||
|
# Go does not provide any equivalent to the regparm function
|
||||||
|
# attribute, so on Go we do not need to worry about passing
|
||||||
|
# parameters in registers. We just pass a pointer to the
|
||||||
|
# arguments on the stack.
|
||||||
|
#
|
||||||
|
# We do need to pick up the return values, though, so we pass
|
||||||
|
# a pointer to a struct that looks like this.
|
||||||
|
# struct {
|
||||||
|
# esp uint32 // 0x0
|
||||||
|
# eax uint32 // 0x4
|
||||||
|
# st0 uint64 // 0x8
|
||||||
|
# }
|
||||||
|
|
||||||
|
pushl %ebp
|
||||||
|
.cfi_def_cfa_offset 8
|
||||||
|
.cfi_offset %ebp, -8
|
||||||
|
movl %esp, %ebp
|
||||||
|
.cfi_def_cfa_register %ebp
|
||||||
|
|
||||||
|
pushl %ebx # In case this is PIC.
|
||||||
|
|
||||||
|
subl $36, %esp # Enough for args and to align stack.
|
||||||
|
.cfi_offset %ebx, -12
|
||||||
|
|
||||||
|
#ifdef __PIC__
|
||||||
|
call __x86.get_pc_thunk.bx
|
||||||
|
addl $_GLOBAL_OFFSET_TABLE_, %ebx
|
||||||
|
#endif
|
||||||
|
|
||||||
|
leal 8(%ebp), %eax # Set esp field in struct.
|
||||||
|
movl %eax, -24(%ebp)
|
||||||
|
|
||||||
|
#ifdef __PIC__
|
||||||
|
call __go_get_closure@PLT
|
||||||
|
#else
|
||||||
|
call __go_get_closure
|
||||||
|
#endif
|
||||||
|
|
||||||
|
movl %eax, 4(%esp)
|
||||||
|
|
||||||
|
leal -24(%ebp), %eax
|
||||||
|
movl %eax, (%esp)
|
||||||
|
|
||||||
|
#ifdef __PIC__
|
||||||
|
call reflect.MakeFuncStubGo@PLT
|
||||||
|
#else
|
||||||
|
call reflect.MakeFuncStubGo
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# Set return registers.
|
||||||
|
|
||||||
|
movl -20(%ebp), %eax
|
||||||
|
fldl -16(%ebp)
|
||||||
|
|
||||||
|
#ifdef __SSE2__
|
||||||
|
# In case we are compiling with -msseregparm. This won't work
|
||||||
|
# correctly if only SSE1 is supported, but that seems unlikely.
|
||||||
|
movsd -16(%ebp), %xmm0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
addl $36, %esp
|
||||||
|
popl %ebx
|
||||||
|
.cfi_restore %ebx
|
||||||
|
popl %ebp
|
||||||
|
.cfi_restore %ebp
|
||||||
|
.cfi_def_cfa %esp, 4
|
||||||
|
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
|
||||||
|
#ifdef __ELF__
|
||||||
|
.size reflect.makeFuncStub, . - reflect.makeFuncStub
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __PIC__
|
||||||
|
.section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
|
||||||
|
.globl __x86.get_pc_thunk.bx
|
||||||
|
.hidden __x86.get_pc_thunk.bx
|
||||||
|
#ifdef __ELF__
|
||||||
|
.type __x86.get_pc_thunk.bx, @function
|
||||||
|
#endif
|
||||||
|
__x86.get_pc_thunk.bx:
|
||||||
|
.cfi_startproc
|
||||||
|
movl (%esp), %ebx
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
#ifdef __ELF__
|
||||||
|
.size __x86.get_pc_thunk.bx, . - __x86.get_pc_thunk.bx
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __ELF__
|
||||||
|
.section .note.GNU-stack,"",@progbits
|
||||||
|
.section .note.GNU-split-stack,"",@progbits
|
||||||
|
.section .note.GNU-no-split-stack,"",@progbits
|
||||||
|
#endif
|
|
@ -0,0 +1,135 @@
|
||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// MakeFunc 386 implementation.
|
||||||
|
|
||||||
|
package reflect
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// The assembler stub will pass a pointer to this structure. We
|
||||||
|
// assume that no parameters are passed in registers--that is, we do
|
||||||
|
// not support the -mregparm option. On return we will set the
|
||||||
|
// registers that might hold result values.
|
||||||
|
type i386Regs struct {
|
||||||
|
esp uint32
|
||||||
|
eax uint32 // Value to return in %eax.
|
||||||
|
st0 uint64 // Value to return in %st(0).
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeFuncStubGo implements the 386 calling convention for MakeFunc.
|
||||||
|
// This should not be called. It is exported so that assembly code
|
||||||
|
// can call it.
|
||||||
|
|
||||||
|
func MakeFuncStubGo(regs *i386Regs, c *makeFuncImpl) {
|
||||||
|
ftyp := c.typ
|
||||||
|
|
||||||
|
// See if the result requires a struct. If it does, the first
|
||||||
|
// parameter is a pointer to the struct.
|
||||||
|
retStruct := false
|
||||||
|
retEmpty := false
|
||||||
|
switch len(ftyp.out) {
|
||||||
|
case 0:
|
||||||
|
retEmpty = true
|
||||||
|
case 1:
|
||||||
|
if ftyp.out[0].size == 0 {
|
||||||
|
retEmpty = true
|
||||||
|
} else {
|
||||||
|
switch ftyp.out[0].Kind() {
|
||||||
|
case Complex64, Complex128, Array, Interface, Slice, String, Struct:
|
||||||
|
retStruct = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
size := uintptr(0)
|
||||||
|
for _, typ := range ftyp.out {
|
||||||
|
size += typ.size
|
||||||
|
}
|
||||||
|
if size == 0 {
|
||||||
|
retEmpty = true
|
||||||
|
} else {
|
||||||
|
retStruct = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
in := make([]Value, 0, len(ftyp.in))
|
||||||
|
ap := uintptr(regs.esp)
|
||||||
|
|
||||||
|
var retPtr unsafe.Pointer
|
||||||
|
if retStruct {
|
||||||
|
retPtr = *(*unsafe.Pointer)(unsafe.Pointer(ap))
|
||||||
|
ap += ptrSize
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rt := range ftyp.in {
|
||||||
|
ap = align(ap, ptrSize)
|
||||||
|
|
||||||
|
// We have to copy the argument onto the heap in case
|
||||||
|
// the function hangs on the reflect.Value we pass it.
|
||||||
|
p := unsafe_New(rt)
|
||||||
|
memmove(p, unsafe.Pointer(ap), rt.size)
|
||||||
|
|
||||||
|
v := Value{rt, p, flag(rt.Kind()<<flagKindShift) | flagIndir}
|
||||||
|
in = append(in, v)
|
||||||
|
ap += rt.size
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the real function.
|
||||||
|
|
||||||
|
out := c.fn(in)
|
||||||
|
|
||||||
|
if len(out) != len(ftyp.out) {
|
||||||
|
panic("reflect: wrong return count from function created by MakeFunc")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, typ := range ftyp.out {
|
||||||
|
v := out[i]
|
||||||
|
if v.typ != typ {
|
||||||
|
panic("reflect: function created by MakeFunc using " + funcName(c.fn) +
|
||||||
|
" returned wrong type: have " +
|
||||||
|
out[i].typ.String() + " for " + typ.String())
|
||||||
|
}
|
||||||
|
if v.flag&flagRO != 0 {
|
||||||
|
panic("reflect: function created by MakeFunc using " + funcName(c.fn) +
|
||||||
|
" returned value obtained from unexported field")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if retEmpty {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if retStruct {
|
||||||
|
off := uintptr(0)
|
||||||
|
for i, typ := range ftyp.out {
|
||||||
|
v := out[i]
|
||||||
|
off = align(off, uintptr(typ.fieldAlign))
|
||||||
|
addr := unsafe.Pointer(uintptr(retPtr) + off)
|
||||||
|
if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
|
||||||
|
storeIword(addr, iword(v.val), typ.size)
|
||||||
|
} else {
|
||||||
|
memmove(addr, v.val, typ.size)
|
||||||
|
}
|
||||||
|
off += typ.size
|
||||||
|
}
|
||||||
|
regs.eax = uint32(uintptr(retPtr))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ftyp.out) != 1 {
|
||||||
|
panic("inconsistency")
|
||||||
|
}
|
||||||
|
|
||||||
|
v := out[0]
|
||||||
|
w := v.iword()
|
||||||
|
if v.Kind() != Ptr && v.Kind() != UnsafePointer {
|
||||||
|
w = loadIword(unsafe.Pointer(w), v.typ.size)
|
||||||
|
}
|
||||||
|
switch v.Kind() {
|
||||||
|
case Float32, Float64:
|
||||||
|
regs.st0 = uint64(uintptr(w))
|
||||||
|
default:
|
||||||
|
regs.eax = uint32(uintptr(w))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue