diff options
author | Richard Henderson <rth@redhat.com> | 2015-01-16 14:58:53 -0800 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2015-01-16 22:58:53 +0000 |
commit | 38bf819a5f995ae4621496df2324d68b9e24900f (patch) | |
tree | c90d2bfba44756e26640c50ad1389375693ef832 /libgo/go/reflect | |
parent | 21cb351825d45c42e9e5148715a2fd2051cf4ed1 (diff) | |
download | gcc-38bf819a5f995ae4621496df2324d68b9e24900f.tar.gz |
compiler, reflect, runtime: Use static chain for closures.
Change from using __go_set_closure to passing the closure
value in the static chain field. Uses new backend support for
setting the closure chain in a call from C via
__builtin_call_with_static_chain. Uses new support in libffi
for Go closures.
The old architecture specific support for reflect.MakeFunc is
removed, replaced by the libffi support.
All work done by Richard Henderson.
* go-gcc.cc (Gcc_backend::call_expression): Add chain_expr argument.
(Gcc_backend::static_chain_variable): New method.
From-SVN: r219776
Diffstat (limited to 'libgo/go/reflect')
-rw-r--r-- | libgo/go/reflect/makefunc.go | 61 | ||||
-rw-r--r-- | libgo/go/reflect/makefunc_386.S | 230 | ||||
-rw-r--r-- | libgo/go/reflect/makefunc_amd64.S | 177 | ||||
-rw-r--r-- | libgo/go/reflect/makefunc_dummy.c | 15 | ||||
-rw-r--r-- | libgo/go/reflect/makefunc_ffi.go | 67 | ||||
-rw-r--r-- | libgo/go/reflect/makefunc_ffi_c.c | 68 | ||||
-rw-r--r-- | libgo/go/reflect/makefunc_s390.c | 86 | ||||
-rw-r--r-- | libgo/go/reflect/makefuncgo_386.go | 139 | ||||
-rw-r--r-- | libgo/go/reflect/makefuncgo_amd64.go | 496 | ||||
-rw-r--r-- | libgo/go/reflect/makefuncgo_s390.go | 454 | ||||
-rw-r--r-- | libgo/go/reflect/makefuncgo_s390x.go | 436 | ||||
-rw-r--r-- | libgo/go/reflect/value.go | 24 |
12 files changed, 48 insertions, 2205 deletions
diff --git a/libgo/go/reflect/makefunc.go b/libgo/go/reflect/makefunc.go index 276be26108f..71aadfbceec 100644 --- a/libgo/go/reflect/makefunc.go +++ b/libgo/go/reflect/makefunc.go @@ -7,25 +7,24 @@ package reflect import ( - "runtime" "unsafe" ) // makeFuncImpl is the closure value implementing the function // returned by MakeFunc. type makeFuncImpl struct { - code uintptr - typ *funcType - fn func([]Value) []Value + // These first three words are layed out like ffi_go_closure. + code uintptr + ffi_cif unsafe.Pointer + ffi_fun func(unsafe.Pointer, unsafe.Pointer) + + typ *funcType + fn func([]Value) []Value // For gccgo we use the same entry point for functions and for // method values. method int rcvr Value - - // When using FFI, hold onto the FFI closure for the garbage - // collector. - ffi *ffiData } // MakeFunc returns a new function of the given Type @@ -58,37 +57,17 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value { t := typ.common() ftyp := (*funcType)(unsafe.Pointer(t)) - var code uintptr - var ffi *ffiData - switch runtime.GOARCH { - case "amd64", "386", "s390", "s390x": - // Indirect Go func value (dummy) to obtain actual - // code address. (A Go func value is a pointer to a C - // function pointer. http://golang.org/s/go11func.) - dummy := makeFuncStub - code = **(**uintptr)(unsafe.Pointer(&dummy)) - default: - code, ffi = makeFuncFFI(ftyp, fn) - } - impl := &makeFuncImpl{ - code: code, typ: ftyp, fn: fn, method: -1, - ffi: ffi, } + makeFuncFFI(ftyp, impl) + return Value{t, unsafe.Pointer(&impl), flag(Func) | flagIndir} } -// makeFuncStub is an assembly function that is the code half of -// the function returned from MakeFunc. It expects a *callReflectFunc -// as its context register, and its job is to invoke callReflect(ctxt, frame) -// where ctxt is the context register and frame is a pointer to the first -// word in the passed-in argument frame. -func makeFuncStub() - // makeMethodValue converts v from the rcvr+method index representation // of a method value to an actual method func value, which is // basically the receiver value with a special bit set, into a true @@ -123,16 +102,7 @@ func makeMethodValue(op string, v Value) Value { rcvr: rcvr, } - switch runtime.GOARCH { - case "amd64", "386": - // Indirect Go func value (dummy) to obtain actual - // code address. (A Go func value is a pointer to a C - // function pointer. http://golang.org/s/go11func.) - dummy := makeFuncStub - fv.code = **(**uintptr)(unsafe.Pointer(&dummy)) - default: - fv.code, fv.ffi = makeFuncFFI(ftyp, fv.call) - } + makeFuncFFI(ftyp, fv) return Value{ft, unsafe.Pointer(&fv), v.flag&flagRO | flag(Func) | flagIndir} } @@ -158,16 +128,7 @@ func makeValueMethod(v Value) Value { rcvr: v, } - switch runtime.GOARCH { - case "amd64", "386", "s390", "s390x": - // Indirect Go func value (dummy) to obtain actual - // code address. (A Go func value is a pointer to a C - // function pointer. http://golang.org/s/go11func.) - dummy := makeFuncStub - impl.code = **(**uintptr)(unsafe.Pointer(&dummy)) - default: - impl.code, impl.ffi = makeFuncFFI(ftyp, impl.call) - } + makeFuncFFI(ftyp, impl) return Value{t, unsafe.Pointer(&impl), v.flag&flagRO | flag(Func) | flagIndir} } diff --git a/libgo/go/reflect/makefunc_386.S b/libgo/go/reflect/makefunc_386.S deleted file mode 100644 index 0e2e7646532..00000000000 --- a/libgo/go/reflect/makefunc_386.S +++ /dev/null @@ -1,230 +0,0 @@ -/* 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. */ - -#include "config.h" - - .globl reflect.makeFuncStub - -#ifdef __ELF__ - .type reflect.makeFuncStub,@function -#endif - -reflect.makeFuncStub: -.LFB1: - - /* 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 float64 // 0x8 - sr bool // 0x10 - sf bool // 0x11 - } - The sr field is set by the function to a non-zero value if - the function takes a struct hidden pointer that must be - popped off the stack. */ - - pushl %ebp -.LCFI0: - movl %esp, %ebp -.LCFI1: - pushl %ebx /* In case this is PIC. */ - subl $36, %esp /* Enough for args and to align stack. */ -.LCFI2: - -#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) - - /* For MakeFunc functions that call recover. */ - movl 4(%ebp), %eax - movl %eax, (%esp) -#ifdef __PIC__ - call __go_makefunc_can_recover@PLT -#else - call __go_makefunc_can_recover -#endif - -#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 - - /* MakeFunc functions can no longer call recover. */ -#ifdef __PIC__ - call __go_makefunc_returning@PLT -#else - call __go_makefunc_returning -#endif - - /* Set return registers. */ - - movl -20(%ebp), %eax - - cmpb $0, -7(%ebp) - je 2f - - 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 - -2: - movb -8(%ebp), %dl - - addl $36, %esp - popl %ebx -.LCFI3: - popl %ebp -.LCFI4: - - testb %dl,%dl - jne 1f - ret -1: - ret $4 -.LFE1: -#ifdef __ELF__ - .size reflect.makeFuncStub, . - reflect.makeFuncStub -#endif - -#ifdef __PIC__ -#ifdef HAVE_AS_COMDAT_GAS - .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat -#else - /* Sun as needs a different syntax. */ - .section .text.__x86.get_pc_thunk.bx%__x86.get_pc_thunk.bx,"ax",@progbits - .group __x86.get_pc_thunk.bx,.text.__x86.get_pc_thunk.bx%__x86.get_pc_thunk.bx,#comdat -#endif - .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: -.LFB2: - movl (%esp), %ebx - ret -.LFE2: -#ifdef __ELF__ - .size __x86.get_pc_thunk.bx, . - __x86.get_pc_thunk.bx -#endif -#endif - -#ifdef __ELF__ -#if defined __PIC__ -# if defined __sun__ && defined __svr4__ -/* 32-bit Solaris 2/x86 uses datarel encoding for PIC. GNU ld before 2.22 - doesn't correctly sort .eh_frame_hdr with mixed encodings, so match this. */ -# define FDE_ENCODING 0x30 /* datarel */ -# define FDE_ENCODE(X) X@GOTOFF -# else -# define FDE_ENCODING 0x1b /* pcrel sdata4 */ -# if defined HAVE_AS_X86_PCREL -# define FDE_ENCODE(X) X-. -# else -# define FDE_ENCODE(X) X@rel -# endif -# endif -#else -# define FDE_ENCODING 0 /* absolute */ -# define FDE_ENCODE(X) X -#endif - - .section .eh_frame,EH_FRAME_FLAGS,@progbits -.Lframe1: - .long .LECIE1-.LSCIE1 /* Length of Common Information Entry */ -.LSCIE1: - .long 0x0 /* CIE Identifier Tag */ - .byte 0x1 /* CIE Version */ - .ascii "zR\0" /* CIE Augmentation */ - .byte 0x1 /* .uleb128 0x1; CIE Code Alignment Factor */ - .byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */ - .byte 0x8 /* CIE RA Column */ - .byte 0x1 /* .uleb128 0x1; Augmentation size */ - .byte FDE_ENCODING - .byte 0xc /* DW_CFA_def_cfa */ - .byte 0x4 /* .uleb128 0x4 */ - .byte 0x4 /* .uleb128 0x4 */ - .byte 0x88 /* DW_CFA_offset, column 0x8 */ - .byte 0x1 /* .uleb128 0x1 */ - .align 4 -.LECIE1: -.LSFDE1: - .long .LEFDE1-.LASFDE1 /* FDE Length */ -.LASFDE1: - .long .LASFDE1-.Lframe1 /* FDE CIE offset */ - .long FDE_ENCODE(.LFB1) /* FDE initial location */ - .long .LFE1-.LFB1 /* FDE address range */ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI0-.LFB1 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 */ - .byte 0x2 /* .uleb128 0x2 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI1-.LCFI0 - .byte 0xd /* DW_CFA_def_cfa_register */ - .byte 0x5 /* .uleb128 0x5 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI2-.LCFI1 - .byte 0x83 /* .DW_CFA_offset, column 0x3 */ - .byte 0x3 /* .uleb128 0x3 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI3-.LCFI2 - .byte 0xc3 /* DW_CFA_restore, column 0x3 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI4-.LCFI3 - .byte 0xc5 /* DW_CFA_restore, column 0x5 */ - .byte 0xc /* DW_CFA_def_cfa */ - .byte 0x4 /* .uleb128 0x4 */ - .byte 0x4 /* .uleb128 0x4 */ - .align 4 -.LEFDE1: -#ifdef __PIC__ -.LSFDE2: - .long .LEFDE2-.LASFDE2 /* FDE Length */ -.LASFDE2: - .long .LASFDE2-.Lframe1 /* FDE CIE offset */ - .long FDE_ENCODE(.LFB2) /* FDE initial location */ - .long .LFE2-.LFB2 /* FDE address range */ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ - .align 4 -.LEFDE2: -#endif /* __PIC__ */ -#endif /* __ELF__ */ - -#if defined(__ELF__) && defined(__linux__) - .section .note.GNU-stack,"",@progbits - .section .note.GNU-split-stack,"",@progbits - .section .note.GNU-no-split-stack,"",@progbits -#endif diff --git a/libgo/go/reflect/makefunc_amd64.S b/libgo/go/reflect/makefunc_amd64.S deleted file mode 100644 index 88302eee1b2..00000000000 --- a/libgo/go/reflect/makefunc_amd64.S +++ /dev/null @@ -1,177 +0,0 @@ -# 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 amd64 assembly code. - -#include "config.h" - - .global reflect.makeFuncStub - -#ifdef __ELF__ - .type reflect.makeFuncStub,@function -#endif - -reflect.makeFuncStub: -.LFB1: - - # Store all the parameter registers in a struct that looks - # like: - # struct { - # rax uint64 // 0x0 - # rdi uint64 // 0x8 - # rsi uint64 // 0x10 - # rdx uint64 // 0x18 - # rcx uint64 // 0x20 - # r8 uint64 // 0x28 - # r9 uint64 // 0x30 - # rsp uint64 // 0x38 Pointer to arguments on stack. - # xmm0 [2]uint64 // 0x40 - # xmm1 [2]uint64 // 0x50 - # xmm2 [2]uint64 // 0x60 - # xmm3 [2]uint64 // 0x70 - # xmm4 [2]uint64 // 0x80 - # xmm5 [2]uint64 // 0x90 - # xmm6 [2]uint64 // 0xa0 - # xmm7 [2]uint64 // 0xb0 - # }; - - pushq %rbp -.LCFI0: - movq %rsp, %rbp -.LCFI1: - - subq $0xc0, %rsp # Space for struct on stack. - - movq %rax, 0x0(%rsp) - movq %rdi, 0x8(%rsp) - movq %rsi, 0x10(%rsp) - movq %rdx, 0x18(%rsp) - movq %rcx, 0x20(%rsp) - movq %r8, 0x28(%rsp) - movq %r9, 0x30(%rsp) - leaq 16(%rbp), %rax - movq %rax, 0x38(%rsp) - movdqa %xmm0, 0x40(%rsp) - movdqa %xmm1, 0x50(%rsp) - movdqa %xmm2, 0x60(%rsp) - movdqa %xmm3, 0x70(%rsp) - movdqa %xmm4, 0x80(%rsp) - movdqa %xmm5, 0x90(%rsp) - movdqa %xmm6, 0xa0(%rsp) - movdqa %xmm7, 0xb0(%rsp) - - /* For MakeFunc functions that call recover. */ - movq 8(%rbp), %rdi -#ifdef __PIC__ - call __go_makefunc_can_recover@PLT -#else - call __go_makefunc_can_recover -#endif - - # Get function type. -#ifdef __PIC__ - call __go_get_closure@PLT -#else - call __go_get_closure -#endif - movq %rax, %rsi - - movq %rsp, %rdi - -#ifdef __PIC__ - call reflect.MakeFuncStubGo@PLT -#else - call reflect.MakeFuncStubGo -#endif - - /* MakeFunc functions can no longer call recover. */ -#ifdef __PIC__ - call __go_makefunc_returning@PLT -#else - call __go_makefunc_returning -#endif - - # The structure will be updated with any return values. Load - # all possible return registers before returning to the caller. - - movq 0x0(%rsp), %rax - movq 0x18(%rsp), %rdx - movq 0x8(%rsp), %rdi - movq 0x10(%rsp), %rsi - movdqa 0x40(%rsp), %xmm0 - movdqa 0x50(%rsp), %xmm1 - - # long double values are returned on the floating point stack, - # but we don't worry about that since Go doesn't have a long - # double type. - - leave -.LCFI2: - - ret -.LFE1: - -#ifdef __ELF__ - .size reflect.makeFuncStub, . - reflect.makeFuncStub -#endif - -#ifdef __ELF__ -#ifdef HAVE_AS_X86_64_UNWIND_SECTION_TYPE - .section .eh_frame,"a",@unwind -#else - .section .eh_frame,"a",@progbits -#endif -.Lframe1: - .long .LECIE1-.LSCIE1 /* Length of Common Information Entry */ -.LSCIE1: - .long 0x0 /* CIE Identifier Tag */ - .byte 0x1 /* CIE Version */ - .ascii "zR\0" /* CIE Augmentation */ - .uleb128 1 /* CIE Code Alignment Factor */ - .sleb128 -8 /* CIE Data Alignment Factor */ - .byte 0x10 /* CIE RA Column */ - .uleb128 1 /* Augmentation size */ - .byte 0x1b /* FDE Encoding (pcrel sdata4) */ - .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ - .uleb128 7 - .uleb128 8 - .byte 0x80+16 /* DW_CFA_offset, %rip offset 1*-8 */ - .uleb128 1 - .align 8 -.LECIE1: -.LSFDE1: - .long .LEFDE1-.LASFDE1 /* FDE Length */ -.LASFDE1: - .long .LASFDE1-.Lframe1 /* FDE CIE offset */ -#if HAVE_AS_X86_PCREL - .long .LFB1-. /* FDE initial location */ -#else - .long .LFB1@rel -#endif - .long .LFE1-.LFB1 /* FDE address range */ - .uleb128 0x0 /* Augmentation size */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI0-.LFB1 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .uleb128 16 - .byte 0x86 /* DW_CFA_offset, column 0x6 */ - .uleb128 2 - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI1-.LCFI0 - .byte 0xd /* DW_CFA_def_cfa_register */ - .uleb128 6 - .byte 0x2 /* DW_CFA_advance_loc1 */ - .byte .LCFI2-.LCFI1 - .byte 0xc /* DW_CFA_def_cfa */ - .uleb128 7 - .uleb128 8 - .align 8 -.LEFDE1: -#endif /* __ELF__ */ - -#if defined(__ELF__) && defined(__linux__) - .section .note.GNU-stack,"",@progbits - .section .note.GNU-split-stack,"",@progbits - .section .note.GNU-no-split-stack,"",@progbits -#endif diff --git a/libgo/go/reflect/makefunc_dummy.c b/libgo/go/reflect/makefunc_dummy.c deleted file mode 100644 index 8eff0c1dfac..00000000000 --- a/libgo/go/reflect/makefunc_dummy.c +++ /dev/null @@ -1,15 +0,0 @@ -// 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. - -#include "runtime.h" - -/* Dummy function for processors that implement MakeFunc using FFI - rather than having builtin support. */ - -void makeFuncStub (void) __asm__ ("reflect.makeFuncStub"); - -void makeFuncStub (void) -{ - runtime_throw ("impossible call to makeFuncStub"); -} diff --git a/libgo/go/reflect/makefunc_ffi.go b/libgo/go/reflect/makefunc_ffi.go index 40c1ea80fbe..6b61f231127 100644 --- a/libgo/go/reflect/makefunc_ffi.go +++ b/libgo/go/reflect/makefunc_ffi.go @@ -5,52 +5,27 @@ package reflect import ( - "runtime" "unsafe" ) -// The ffi function, written in C, allocates an FFI closure. It -// returns the code and data pointers. When the code pointer is -// called, it will call callback. CIF is an FFI data structure -// allocated as part of the closure, and is returned to ensure that -// the GC retains it. -func ffi(ftyp *funcType, callback func(unsafe.Pointer, unsafe.Pointer)) (code uintptr, data uintptr, cif unsafe.Pointer) - -// The ffiFree function, written in C, releases the FFI closure. -func ffiFree(uintptr) - -// An ffiData holds the information needed to preserve an FFI closure -// for the garbage collector. -type ffiData struct { - code uintptr - data uintptr - cif unsafe.Pointer - callback func(unsafe.Pointer, unsafe.Pointer) -} - -// The makeFuncFFI function uses libffi closures to implement -// reflect.MakeFunc. This is used for processors for which we don't -// have more efficient support. -func makeFuncFFI(ftyp *funcType, fn func(args []Value) (results []Value)) (uintptr, *ffiData) { - callback := func(params, results unsafe.Pointer) { - ffiCall(ftyp, fn, params, results) - } - - code, data, cif := ffi(ftyp, callback) - - c := &ffiData{code: code, data: data, cif: cif, callback: callback} - - runtime.SetFinalizer(c, - func(p *ffiData) { - ffiFree(p.data) - }) - - return code, c -} - -// ffiCall takes pointers to the parameters, calls the function, and -// stores the results back into memory. -func ffiCall(ftyp *funcType, fn func([]Value) []Value, params unsafe.Pointer, results unsafe.Pointer) { +// The makeFuncFFI function, written in C, fills in an FFI closure. +// It arranges for ffiCall to be invoked directly from FFI. +func makeFuncFFI(ftyp *funcType, impl *makeFuncImpl) + +// FFICallbackGo implements the Go side of the libffi callback. +// It is exported so that C code can call it. +// +// The call chain arriving here looks like +// some_go_caller +// ->some_ffi_internals +// ->ffi_callback (in C) +// ->FFICallbackGo +// +// The ffi_callback handles __go_makefunc_can_recover, and +// then passes off the data as received from ffi here. + +func FFICallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFuncImpl) { + ftyp := impl.typ in := make([]Value, 0, len(ftyp.in)) ap := params for _, rt := range ftyp.in { @@ -61,18 +36,18 @@ func ffiCall(ftyp *funcType, fn func([]Value) []Value, params unsafe.Pointer, re ap = (unsafe.Pointer)(uintptr(ap) + ptrSize) } - out := fn(in) + out := impl.call(in) off := uintptr(0) for i, typ := range ftyp.out { v := out[i] if v.typ != typ { - panic("reflect: function created by MakeFunc using " + funcName(fn) + + panic("reflect: function created by MakeFunc using " + funcName(impl.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(fn) + + panic("reflect: function created by MakeFunc using " + funcName(impl.fn) + " returned value obtained from unexported field") } diff --git a/libgo/go/reflect/makefunc_ffi_c.c b/libgo/go/reflect/makefunc_ffi_c.c index a3dfd4acd2c..727ae8180ad 100644 --- a/libgo/go/reflect/makefunc_ffi_c.c +++ b/libgo/go/reflect/makefunc_ffi_c.c @@ -10,7 +10,7 @@ #include "go-ffi.h" -#if FFI_CLOSURES +#if FFI_GO_CLOSURES #define USE_LIBFFI_CLOSURES #endif @@ -18,36 +18,28 @@ /* Declare C functions with the names used to call from Go. */ -struct ffi_ret { - void *code; - void *data; - void *cif; -}; - -struct ffi_ret ffi(const struct __go_func_type *ftyp, FuncVal *callback) - __asm__ (GOSYM_PREFIX "reflect.ffi"); - -void ffiFree(void *data) - __asm__ (GOSYM_PREFIX "reflect.ffiFree"); +void makeFuncFFI(const struct __go_func_type *ftyp, ffi_go_closure *impl) + __asm__ (GOSYM_PREFIX "reflect.makeFuncFFI"); #ifdef USE_LIBFFI_CLOSURES -/* The function that we pass to ffi_prep_closure_loc. This calls the - Go callback function (passed in user_data) with the pointer to the - arguments and the results area. */ +/* The function that we pass to ffi_prep_closure_loc. This calls the Go + function ffiCall with the pointer to the arguments, the results area, + and the closure structure. */ + +void FFICallbackGo(void *result, void **args, ffi_go_closure *closure) + __asm__ (GOSYM_PREFIX "reflect.FFICallbackGo"); static void ffi_callback (ffi_cif *, void *, void **, void *) __asm__ ("reflect.ffi_callback"); static void ffi_callback (ffi_cif* cif __attribute__ ((unused)), void *results, - void **args, void *user_data) + void **args, void *closure) { Location locs[8]; int n; int i; - FuncVal *fv; - void (*f) (void *, void *); /* This function is called from some series of FFI closure functions called by a Go function. We want to see whether the caller of @@ -69,10 +61,7 @@ ffi_callback (ffi_cif* cif __attribute__ ((unused)), void *results, if (i < n) __go_makefunc_ffi_can_recover (locs + i, n - i); - fv = (FuncVal *) user_data; - __go_set_closure (fv); - f = (void *) fv->fn; - f (args, results); + FFICallbackGo(results, args, closure); if (i < n) __go_makefunc_returning (); @@ -80,46 +69,21 @@ ffi_callback (ffi_cif* cif __attribute__ ((unused)), void *results, /* Allocate an FFI closure and arrange to call ffi_callback. */ -struct ffi_ret -ffi (const struct __go_func_type *ftyp, FuncVal *callback) +void +makeFuncFFI(const struct __go_func_type *ftyp, ffi_go_closure *impl) { ffi_cif *cif; - void *code; - void *data; - struct ffi_ret ret; cif = (ffi_cif *) __go_alloc (sizeof (ffi_cif)); __go_func_to_cif (ftyp, 0, 0, cif); - data = ffi_closure_alloc (sizeof (ffi_closure), &code); - if (data == NULL) - runtime_panicstring ("ffi_closure_alloc failed"); - if (ffi_prep_closure_loc (data, cif, ffi_callback, callback, code) - != FFI_OK) - runtime_panicstring ("ffi_prep_closure_loc failed"); - ret.code = code; - ret.data = data; - ret.cif = cif; - return ret; -} - -/* Free the FFI closure. */ -void -ffiFree (void *data) -{ - ffi_closure_free (data); + ffi_prep_go_closure(impl, cif, ffi_callback); } #else /* !defined(USE_LIBFFI_CLOSURES) */ -struct ffi_ret -ffi(const struct __go_func_type *ftyp, FuncVal *callback) -{ - runtime_panicstring ("libgo built without FFI does not support " - "reflect.MakeFunc"); -} - -void ffiFree(void *data) +void +makeFuncFFI(const struct __go_func_type *ftyp, ffi_go_closure *impl) { runtime_panicstring ("libgo built without FFI does not support " "reflect.MakeFunc"); diff --git a/libgo/go/reflect/makefunc_s390.c b/libgo/go/reflect/makefunc_s390.c deleted file mode 100644 index 78a960ca2f6..00000000000 --- a/libgo/go/reflect/makefunc_s390.c +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2014 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. - -#include "runtime.h" -#include "go-panic.h" - -#ifdef __s390x__ -# define S390_GO_USE_64_BIT_ABI 1 -# define S390_GO_S390X_ARGS , double f4, double f6 -# define S390_GO_S390X_FIELDS double f4; double f6; - extern void S390xMakeFuncStubGo(void *, void *) - asm ("reflect.S390xMakeFuncStubGo"); -# define S390_GO_MakeFuncStubGo(r, c) S390xMakeFuncStubGo((r), (c)) -#else -# define S390_GO_USE_64_BIT_ABI 0 -# define S390_GO_S390X_ARGS -# define S390_GO_S390X_FIELDS - extern void S390MakeFuncStubGo(void *, void *) - asm ("reflect.S390MakeFuncStubGo"); -# define S390_GO_MakeFuncStubGo(r, c) S390MakeFuncStubGo((r), (c)) - /* Needed to make the unused 64 bit abi conditional code compile. */ -# define f4 f0 -# define f6 f2 -#endif - -/* Structure to store all registers used for parameter passing. */ -typedef struct -{ - long r2; - long r3; - long r4; - long r5; - long r6; - /* Pointer to non-register arguments on the stack. */ - long stack_args; - double f0; - double f2; - S390_GO_S390X_FIELDS -} s390Regs; - -void -makeFuncStub(long r2, long r3, long r4, long r5, long r6, - unsigned long stack_args, double f0, double f2 - S390_GO_S390X_ARGS) - asm ("reflect.makeFuncStub"); - -void -makeFuncStub(long r2, long r3, long r4, long r5, long r6, - unsigned long stack_args, double f0, double f2 - S390_GO_S390X_ARGS) -{ - s390Regs regs; - void *closure; - - /* Store the registers in a structure that is passed on to the Go stub - function. */ - regs.r2 = r2; - regs.r3 = r3; - regs.r4 = r4; - regs.r5 = r5; - regs.r6 = r6; - regs.stack_args = (long)&stack_args; - regs.f0 = f0; - regs.f2 = f2; - if (S390_GO_USE_64_BIT_ABI) { - regs.f4 = f4; - regs.f6 = f6; - } - /* For MakeFunc functions that call recover. */ - __go_makefunc_can_recover(__builtin_return_address(0)); - /* Call the Go stub function. */ - closure = __go_get_closure(); - S390_GO_MakeFuncStubGo(®s, closure); - /* MakeFunc functions can no longer call recover. */ - __go_makefunc_returning(); - /* Restore all possible return registers. */ - if (S390_GO_USE_64_BIT_ABI) { - asm volatile ("lg\t%%r2,0(%0)" : : "a" (®s.r2) : "r2" ); - asm volatile ("ld\t%%f0,0(%0)" : : "a" (®s.f0) : "f0" ); - } else { - asm volatile ("l\t%%r2,0(%0)" : : "a" (®s.r2) : "r2" ); - asm volatile ("l\t%%r3,0(%0)" : : "a" (®s.r3) : "r3" ); - asm volatile ("ld\t%%f0,0(%0)" : : "a" (®s.f0) : "f0" ); - } -} diff --git a/libgo/go/reflect/makefuncgo_386.go b/libgo/go/reflect/makefuncgo_386.go deleted file mode 100644 index c20f0ac3b3e..00000000000 --- a/libgo/go/reflect/makefuncgo_386.go +++ /dev/null @@ -1,139 +0,0 @@ -// 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 float64 // Value to return in %st(0). - sr bool // Set to true if hidden struct pointer. - sf bool // Set to true if returning float -} - -// 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) - - regs.sr = false - regs.sf = false - var retPtr unsafe.Pointer - if retStruct { - retPtr = *(*unsafe.Pointer)(unsafe.Pointer(ap)) - ap += ptrSize - regs.sr = true - } - - 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()) | flagIndir} - in = append(in, v) - ap += rt.size - } - - // Call the real function. - - out := c.call(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) { - *(*unsafe.Pointer)(addr) = v.ptr - } else { - memmove(addr, v.ptr, typ.size) - } - off += typ.size - } - regs.eax = uint32(uintptr(retPtr)) - return - } - - if len(ftyp.out) != 1 { - panic("inconsistency") - } - - v := out[0] - switch v.Kind() { - case Ptr, UnsafePointer, Chan, Func, Map: - regs.eax = uint32(uintptr(v.pointer())) - case Float32, Float64: - regs.st0 = v.Float() - regs.sf = true - default: - memmove(unsafe.Pointer(®s.eax), v.ptr, v.typ.size) - } -} diff --git a/libgo/go/reflect/makefuncgo_amd64.go b/libgo/go/reflect/makefuncgo_amd64.go deleted file mode 100644 index a236aa26795..00000000000 --- a/libgo/go/reflect/makefuncgo_amd64.go +++ /dev/null @@ -1,496 +0,0 @@ -// 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 amd64 implementation. - -package reflect - -import "unsafe" - -// The assembler stub will pass a pointer to this structure. -// This will come in holding all the registers that might hold -// function parameters. On return we will set the registers that -// might hold result values. -type amd64Regs struct { - rax uint64 - rdi uint64 - rsi uint64 - rdx uint64 - rcx uint64 - r8 uint64 - r9 uint64 - rsp uint64 - xmm0 [2]uint64 - xmm1 [2]uint64 - xmm2 [2]uint64 - xmm3 [2]uint64 - xmm4 [2]uint64 - xmm5 [2]uint64 - xmm6 [2]uint64 - xmm7 [2]uint64 -} - -// Argument classifications. The amd64 ELF ABI uses several more, but -// these are the only ones that arise for Go types. -type amd64Class int - -const ( - amd64Integer amd64Class = iota - amd64SSE - amd64NoClass - amd64Memory -) - -// amd64Classify returns the one or two register classes needed to -// pass the value of type. Go types never need more than two -// registers. amd64Memory means the value is stored in memory. -// amd64NoClass means the register is not used. -func amd64Classify(typ *rtype) (amd64Class, amd64Class) { - switch typ.Kind() { - default: - panic("internal error--unknown kind in amd64Classify") - - case Bool, Int, Int8, Int16, Int32, Int64, - Uint, Uint8, Uint16, Uint32, Uint64, - Uintptr, Chan, Func, Map, Ptr, UnsafePointer: - - return amd64Integer, amd64NoClass - - case Float32, Float64, Complex64: - return amd64SSE, amd64NoClass - - case Complex128: - return amd64SSE, amd64SSE - - case Array: - if typ.size == 0 { - return amd64NoClass, amd64NoClass - } else if typ.size > 16 { - return amd64Memory, amd64NoClass - } - atyp := (*arrayType)(unsafe.Pointer(typ)) - eclass1, eclass2 := amd64Classify(atyp.elem) - if eclass1 == amd64Memory { - return amd64Memory, amd64NoClass - } - if eclass2 == amd64NoClass && typ.size > 8 { - eclass2 = eclass1 - } - return eclass1, eclass2 - - case Interface: - return amd64Integer, amd64Integer - - case Slice: - return amd64Memory, amd64NoClass - - case String: - return amd64Integer, amd64Integer - - case Struct: - if typ.size == 0 { - return amd64NoClass, amd64NoClass - } else if typ.size > 16 { - return amd64Memory, amd64NoClass - } - var first, second amd64Class - f := amd64NoClass - onFirst := true - styp := (*structType)(unsafe.Pointer(typ)) - for _, field := range styp.fields { - if onFirst && field.offset >= 8 { - first = f - f = amd64NoClass - onFirst = false - } - fclass1, fclass2 := amd64Classify(field.typ) - f = amd64MergeClasses(f, fclass1) - if fclass2 != amd64NoClass { - if !onFirst { - panic("amd64Classify inconsistent") - } - first = f - f = fclass2 - onFirst = false - } - } - if onFirst { - first = f - second = amd64NoClass - } else { - second = f - } - if first == amd64Memory || second == amd64Memory { - return amd64Memory, amd64NoClass - } - return first, second - } -} - -// amd64MergeClasses merges two register classes as described in the -// amd64 ELF ABI. -func amd64MergeClasses(c1, c2 amd64Class) amd64Class { - switch { - case c1 == c2: - return c1 - case c1 == amd64NoClass: - return c2 - case c2 == amd64NoClass: - return c1 - case c1 == amd64Memory || c2 == amd64Memory: - return amd64Memory - case c1 == amd64Integer || c2 == amd64Integer: - return amd64Integer - default: - return amd64SSE - } -} - -// MakeFuncStubGo implements the amd64 calling convention for -// MakeFunc. This should not be called. It is exported so that -// assembly code can call it. - -func MakeFuncStubGo(regs *amd64Regs, c *makeFuncImpl) { - ftyp := c.typ - - // See if the result requires a struct. If it does, the first - // parameter is a pointer to the struct. - var ret1, ret2 amd64Class - switch len(ftyp.out) { - case 0: - ret1, ret2 = amd64NoClass, amd64NoClass - case 1: - ret1, ret2 = amd64Classify(ftyp.out[0]) - default: - off := uintptr(0) - f := amd64NoClass - onFirst := true - for _, rt := range ftyp.out { - off = align(off, uintptr(rt.fieldAlign)) - - if onFirst && off >= 8 { - ret1 = f - f = amd64NoClass - onFirst = false - } - - off += rt.size - if off > 16 { - break - } - - fclass1, fclass2 := amd64Classify(rt) - f = amd64MergeClasses(f, fclass1) - if fclass2 != amd64NoClass { - if !onFirst { - panic("amd64Classify inconsistent") - } - ret1 = f - f = fclass2 - onFirst = false - } - } - if off > 16 { - ret1, ret2 = amd64Memory, amd64NoClass - } else { - if onFirst { - ret1, ret2 = f, amd64NoClass - } else { - ret2 = f - } - } - if ret1 == amd64Memory || ret2 == amd64Memory { - ret1, ret2 = amd64Memory, amd64NoClass - } - } - - in := make([]Value, 0, len(ftyp.in)) - intreg := 0 - ssereg := 0 - ap := uintptr(regs.rsp) - - maxIntregs := 6 // When we support Windows, this would be 4. - maxSSEregs := 8 - - if ret1 == amd64Memory { - // We are returning a value in memory, which means - // that the first argument is a hidden parameter - // pointing to that return area. - intreg++ - } - -argloop: - for _, rt := range ftyp.in { - c1, c2 := amd64Classify(rt) - - fl := flag(rt.Kind()) - if c2 == amd64NoClass { - - // Argument is passed in a single register or - // in memory. - - switch c1 { - case amd64NoClass: - v := Value{rt, nil, fl | flagIndir} - in = append(in, v) - continue argloop - case amd64Integer: - if intreg < maxIntregs { - reg := amd64IntregVal(regs, intreg) - iw := unsafe.Pointer(reg) - if k := rt.Kind(); k != Ptr && k != UnsafePointer { - iw = unsafe.Pointer(®) - fl |= flagIndir - } - v := Value{rt, iw, fl} - in = append(in, v) - intreg++ - continue argloop - } - case amd64SSE: - if ssereg < maxSSEregs { - reg := amd64SSEregVal(regs, ssereg) - v := Value{rt, unsafe.Pointer(®), fl | flagIndir} - in = append(in, v) - ssereg++ - continue argloop - } - } - - in, ap = amd64Memarg(in, ap, rt) - continue argloop - } - - // Argument is passed in two registers. - - nintregs := 0 - nsseregs := 0 - switch c1 { - case amd64Integer: - nintregs++ - case amd64SSE: - nsseregs++ - default: - panic("inconsistent") - } - switch c2 { - case amd64Integer: - nintregs++ - case amd64SSE: - nsseregs++ - default: - panic("inconsistent") - } - - // If the whole argument does not fit in registers, it - // is passed in memory. - - if intreg+nintregs > maxIntregs || ssereg+nsseregs > maxSSEregs { - in, ap = amd64Memarg(in, ap, rt) - continue argloop - } - - var word1, word2 uintptr - switch c1 { - case amd64Integer: - word1 = amd64IntregVal(regs, intreg) - intreg++ - case amd64SSE: - word1 = amd64SSEregVal(regs, ssereg) - ssereg++ - } - switch c2 { - case amd64Integer: - word2 = amd64IntregVal(regs, intreg) - intreg++ - case amd64SSE: - word2 = amd64SSEregVal(regs, ssereg) - ssereg++ - } - - p := unsafe_New(rt) - *(*uintptr)(p) = word1 - *(*uintptr)(unsafe.Pointer(uintptr(p) + ptrSize)) = word2 - v := Value{rt, p, fl | flagIndir} - in = append(in, v) - } - - // All the real arguments have been found and turned into - // Value's. Call the real function. - - out := c.call(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 ret1 == amd64NoClass { - return - } - - if ret1 == amd64Memory { - // The address of the memory area was passed as a - // hidden parameter in %rdi. - ptr := unsafe.Pointer(uintptr(regs.rdi)) - off := uintptr(0) - for i, typ := range ftyp.out { - v := out[i] - off = align(off, uintptr(typ.fieldAlign)) - addr := unsafe.Pointer(uintptr(ptr) + off) - if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) { - *(*unsafe.Pointer)(addr) = v.ptr - } else { - memmove(addr, v.ptr, typ.size) - } - off += typ.size - } - return - } - - if len(out) == 1 && ret2 == amd64NoClass { - v := out[0] - var w unsafe.Pointer - switch v.Kind() { - case Ptr, UnsafePointer, Chan, Func, Map: - w = v.pointer() - default: - memmove(unsafe.Pointer(&w), v.ptr, v.typ.size) - } - switch ret1 { - case amd64Integer: - regs.rax = uint64(uintptr(w)) - case amd64SSE: - regs.xmm0[0] = uint64(uintptr(w)) - regs.xmm0[1] = 0 - default: - panic("inconsistency") - } - return - } - - var buf [2]unsafe.Pointer - ptr := unsafe.Pointer(&buf[0]) - off := uintptr(0) - for i, typ := range ftyp.out { - v := out[i] - off = align(off, uintptr(typ.fieldAlign)) - addr := unsafe.Pointer(uintptr(ptr) + off) - if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) { - *(*unsafe.Pointer)(addr) = v.ptr - } else { - memmove(addr, v.ptr, typ.size) - } - off += uintptr(typ.size) - } - - switch ret1 { - case amd64Integer: - regs.rax = *(*uint64)(unsafe.Pointer(&buf[0])) - case amd64SSE: - regs.xmm0[0] = *(*uint64)(unsafe.Pointer(&buf[0])) - regs.xmm0[1] = 0 - default: - panic("inconsistency") - } - - switch ret2 { - case amd64Integer: - reg := *(*uint64)(unsafe.Pointer(&buf[1])) - if ret1 == amd64Integer { - regs.rdx = reg - } else { - regs.rax = reg - } - case amd64SSE: - reg := *(*uint64)(unsafe.Pointer(&buf[1])) - if ret1 == amd64Integer { - regs.xmm0[0] = reg - regs.xmm0[1] = 0 - } else { - regs.xmm1[0] = reg - regs.xmm1[1] = 0 - } - case amd64NoClass: - default: - panic("inconsistency") - } -} - -// The amd64Memarg function adds an argument passed in memory. -func amd64Memarg(in []Value, ap uintptr, rt *rtype) ([]Value, uintptr) { - ap = align(ap, ptrSize) - ap = align(ap, uintptr(rt.align)) - - // We have to copy the argument onto the heap in case the - // function hangs onto the reflect.Value we pass it. - p := unsafe_New(rt) - memmove(p, unsafe.Pointer(ap), rt.size) - - v := Value{rt, p, flag(rt.Kind()) | flagIndir} - in = append(in, v) - ap += rt.size - return in, ap -} - -// The amd64IntregVal function returns the value of integer register i. -func amd64IntregVal(regs *amd64Regs, i int) uintptr { - var r uint64 - switch i { - case 0: - r = regs.rdi - case 1: - r = regs.rsi - case 2: - r = regs.rdx - case 3: - r = regs.rcx - case 4: - r = regs.r8 - case 5: - r = regs.r9 - default: - panic("amd64IntregVal: bad index") - } - return uintptr(r) -} - -// The amd64SSEregVal function returns the value of SSE register i. -// Note that although SSE registers can hold two uinptr's, for the -// types we use in Go we only ever use the least significant one. The -// most significant one would only be used for 128 bit types. -func amd64SSEregVal(regs *amd64Regs, i int) uintptr { - var r uint64 - switch i { - case 0: - r = regs.xmm0[0] - case 1: - r = regs.xmm1[0] - case 2: - r = regs.xmm2[0] - case 3: - r = regs.xmm3[0] - case 4: - r = regs.xmm4[0] - case 5: - r = regs.xmm5[0] - case 6: - r = regs.xmm6[0] - case 7: - r = regs.xmm7[0] - } - return uintptr(r) -} diff --git a/libgo/go/reflect/makefuncgo_s390.go b/libgo/go/reflect/makefuncgo_s390.go deleted file mode 100644 index 47daa77f6bb..00000000000 --- a/libgo/go/reflect/makefuncgo_s390.go +++ /dev/null @@ -1,454 +0,0 @@ -// Copyright 2014 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 s390 implementation. - -package reflect - -import "unsafe" - -// Convenience types and constants. -const s390_arch_stack_slot_align uintptr = 4 -const s390_num_gr = 5 -const s390_num_fr = 2 - -type s390_arch_gr_t uint32 -type s390_arch_fr_t uint64 - -// The assembler stub will pass a pointer to this structure. -// This will come in holding all the registers that might hold -// function parameters. On return we will set the registers that -// might hold result values. -type s390_regs struct { - r2 s390_arch_gr_t - r3 s390_arch_gr_t - r4 s390_arch_gr_t - r5 s390_arch_gr_t - r6 s390_arch_gr_t - stack_args s390_arch_gr_t - f0 s390_arch_fr_t - f2 s390_arch_fr_t -} - -// Argument classifications that arise for Go types. -type s390_arg_t int - -const ( - s390_general_reg s390_arg_t = iota - s390_general_reg_pair - s390_float_reg - // Argument passed as a pointer to an in-memory value. - s390_mem_ptr - s390_empty -) - -// s390ClassifyParameter returns the register class needed to -// pass the value of type TYP. s390_empty means the register is -// not used. The second and third return values are the offset of -// an rtype parameter passed in a register (second) or stack slot -// (third). -func s390ClassifyParameter(typ *rtype) (s390_arg_t, uintptr, uintptr) { - offset := s390_arch_stack_slot_align - typ.Size() - if typ.Size() > s390_arch_stack_slot_align { - offset = 0 - } - switch typ.Kind() { - default: - panic("internal error--unknown kind in s390ClassifyParameter") - case Bool, Int, Int8, Int16, Int32, Uint, Uint8, Uint16, Uint32: - return s390_general_reg, offset, offset - case Int64, Uint64: - return s390_general_reg_pair, 0, 0 - case Uintptr, Chan, Func, Map, Ptr, UnsafePointer: - return s390_general_reg, 0, 0 - case Float32, Float64: - return s390_float_reg, 0, offset - case Complex64, Complex128: - // Complex numbers are passed by reference. - return s390_mem_ptr, 0, 0 - case Array, Struct: - var ityp *rtype - var length int - - if typ.Size() == 0 { - return s390_empty, 0, 0 - } - switch typ.Size() { - default: - // Pointer to memory. - return s390_mem_ptr, 0, 0 - case 1, 2: - // Pass in an integer register. - return s390_general_reg, offset, offset - - case 4, 8: - // See below. - } - if typ.Kind() == Array { - atyp := (*arrayType)(unsafe.Pointer(typ)) - length = atyp.Len() - ityp = atyp.elem - } else { - styp := (*structType)(unsafe.Pointer(typ)) - length = len(styp.fields) - ityp = styp.fields[0].typ - } - if length == 1 { - class, off_reg, off_slot := s390ClassifyParameter(ityp) - if class == s390_float_reg { - // The array (stored in a structure) or struct - // is "equivalent to a floating point type" as - // defined in the S390 Abi. Note that this - // can only be the case in the case 4 of the - // switch above. - return s390_float_reg, off_reg, off_slot - } - } - switch typ.Size() { - case 4: - return s390_general_reg, offset, offset - case 8: - return s390_general_reg_pair, 0, 0 - default: - return s390_general_reg, 0, 0 - } - case Interface, String: - // Structure of size 8. - return s390_general_reg_pair, 0, 0 - - case Slice: - return s390_mem_ptr, 0, 0 - } -} - -// s390ClassifyReturn returns the register classes needed to -// return the value of type TYP. s390_empty means the register is -// not used. The second value is the offset of an rtype return -// parameter if stored in a register. -func s390ClassifyReturn(typ *rtype) (s390_arg_t, uintptr) { - offset := s390_arch_stack_slot_align - typ.Size() - if typ.Size() > s390_arch_stack_slot_align { - offset = 0 - } - switch typ.Kind() { - default: - panic("internal error--unknown kind in s390ClassifyReturn") - case Bool, Int, Int8, Int16, Int32, - Uint, Uint8, Uint16, Uint32, Uintptr: - - return s390_general_reg, offset - case Int64, Uint64: - return s390_general_reg_pair, 0 - case Chan, Func, Map, Ptr, UnsafePointer: - return s390_general_reg, 0 - case Float32, Float64: - return s390_float_reg, 0 - case Complex64, Complex128: - return s390_mem_ptr, 0 - case Interface, Slice, String: - return s390_mem_ptr, 0 - case Array, Struct: - if typ.size == 0 { - return s390_empty, 0 - } - // No optimization is done for returned structures and arrays. - return s390_mem_ptr, 0 - } -} - -// Given a value of type *rtype left aligned in an unsafe.Pointer, -// reload the value so that it can be stored in a general or -// floating point register. For general registers the value is -// sign extend and right aligned. -func s390ReloadForRegister(typ *rtype, w uintptr, offset uintptr) uintptr { - var do_sign_extend bool = false - var gr s390_arch_gr_t - - switch typ.Kind() { - case Int, Int8, Int16, Int32: - do_sign_extend = true - default: - // Handle all other cases in the next switch. - } - switch typ.size { - case 1: - if do_sign_extend == true { - se := int32(*(*int8)(unsafe.Pointer(&w))) - gr = *(*s390_arch_gr_t)(unsafe.Pointer(&se)) - } else { - e := int32(*(*uint8)(unsafe.Pointer(&w))) - gr = *(*s390_arch_gr_t)(unsafe.Pointer(&e)) - } - case 2: - if do_sign_extend == true { - se := int32(*(*int16)(unsafe.Pointer(&w))) - gr = *(*s390_arch_gr_t)(unsafe.Pointer(&se)) - } else { - e := int32(*(*uint16)(unsafe.Pointer(&w))) - gr = *(*s390_arch_gr_t)(unsafe.Pointer(&e)) - } - default: - panic("reflect: bad size in s390ReloadForRegister") - } - - return *(*uintptr)(unsafe.Pointer(&gr)) -} - -// MakeFuncStubGo implements the s390 calling convention for -// MakeFunc. This should not be called. It is exported so that -// assembly code can call it. -func S390MakeFuncStubGo(regs *s390_regs, c *makeFuncImpl) { - ftyp := c.typ - gr := 0 - fr := 0 - ap := uintptr(regs.stack_args) - - // See if the result requires a struct. If it does, the first - // parameter is a pointer to the struct. - var ret_class s390_arg_t - var ret_off_reg uintptr - var ret_type *rtype - - switch len(ftyp.out) { - case 0: - ret_type = nil - ret_class, ret_off_reg = s390_empty, 0 - case 1: - ret_type = ftyp.out[0] - ret_class, ret_off_reg = s390ClassifyReturn(ret_type) - default: - ret_type = nil - ret_class, ret_off_reg = s390_mem_ptr, 0 - } - in := make([]Value, 0, len(ftyp.in)) - if ret_class == s390_mem_ptr { - // We are returning a value in memory, which means - // that the first argument is a hidden parameter - // pointing to that return area. - gr++ - } - -argloop: - for _, rt := range ftyp.in { - class, off_reg, off_slot := s390ClassifyParameter(rt) - fl := flag(rt.Kind()) - switch class { - case s390_empty: - v := Value{rt, nil, fl | flagIndir} - in = append(in, v) - continue argloop - case s390_general_reg: - // Values stored in a general register are right - // aligned. - if gr < s390_num_gr { - val := s390_general_reg_val(regs, gr) - iw := unsafe.Pointer(&val) - k := rt.Kind() - if k != Ptr && k != UnsafePointer { - ix := uintptr(unsafe.Pointer(&val)) - ix += off_reg - iw = unsafe.Pointer(ix) - fl |= flagIndir - } - v := Value{rt, iw, fl} - in = append(in, v) - gr++ - } else { - in, ap = s390_add_stackreg( - in, ap, rt, off_slot) - } - continue argloop - case s390_general_reg_pair: - // 64-bit integers and structs are passed in a register - // pair. - if gr+1 < s390_num_gr { - val := uint64(s390_general_reg_val(regs, gr))<<32 + uint64(s390_general_reg_val(regs, gr+1)) - iw := unsafe.Pointer(&val) - v := Value{rt, iw, fl | flagIndir} - in = append(in, v) - gr += 2 - } else { - in, ap = s390_add_stackreg(in, ap, rt, off_slot) - gr = s390_num_gr - } - continue argloop - case s390_float_reg: - // In a register, floats are left aligned, but in a - // stack slot they are right aligned. - if fr < s390_num_fr { - val := s390_float_reg_val(regs, fr) - ix := uintptr(unsafe.Pointer(&val)) - v := Value{ - rt, unsafe.Pointer(unsafe.Pointer(ix)), - fl | flagIndir, - } - in = append(in, v) - fr++ - } else { - in, ap = s390_add_stackreg( - in, ap, rt, off_slot) - } - continue argloop - case s390_mem_ptr: - if gr < s390_num_gr { - // Register holding a pointer to memory. - val := s390_general_reg_val(regs, gr) - v := Value{ - rt, unsafe.Pointer(uintptr(val)), - fl | flagIndir} - in = append(in, v) - gr++ - } else { - // Stack slot holding a pointer to memory. - in, ap = s390_add_memarg(in, ap, rt) - } - continue argloop - } - panic("reflect: argtype not handled in MakeFunc:argloop") - } - - // All the real arguments have been found and turned into - // Values. Call the real function. - - out := c.call(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") - } - } - - switch ret_class { - case s390_general_reg, s390_float_reg, s390_general_reg_pair: - // Single return value in a general or floating point register. - v := out[0] - var w uintptr - switch v.Kind() { - case Ptr, UnsafePointer, Chan, Func, Map: - w = uintptr(v.pointer()) - default: - memmove(unsafe.Pointer(&w), v.ptr, v.typ.size) - if ret_off_reg != 0 { - w = s390ReloadForRegister( - ret_type, w, ret_off_reg) - } - } - if ret_class == s390_float_reg { - regs.f0 = s390_arch_fr_t(uintptr(w)) - } else if ret_class == s390_general_reg { - regs.r2 = s390_arch_gr_t(uintptr(w)) - } else { - regs.r2 = s390_arch_gr_t(uintptr(w) >> 32) - regs.r3 = s390_arch_gr_t(uintptr(w) & 0xffffffff) - } - - case s390_mem_ptr: - // The address of the memory area was passed as a hidden - // parameter in %r2. Multiple return values are always returned - // in an in-memory structure. - ptr := unsafe.Pointer(uintptr(regs.r2)) - off := uintptr(0) - for i, typ := range ftyp.out { - v := out[i] - off = align(off, uintptr(typ.fieldAlign)) - addr := unsafe.Pointer(uintptr(ptr) + off) - if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) { - *(*unsafe.Pointer)(addr) = v.ptr - } else { - memmove(addr, v.ptr, typ.size) - } - off += typ.size - } - - case s390_empty: - } - - return -} - -// The s390_add_stackreg function adds an argument passed on the -// stack that could be passed in a register. -func s390_add_stackreg(in []Value, ap uintptr, rt *rtype, offset uintptr) ([]Value, uintptr) { - // If we're not already at the beginning of a stack slot, round up to - // the beginning of the next one. - ap = align(ap, s390_arch_stack_slot_align) - // If offset is > 0, the data is right aligned on the stack slot. - ap += offset - - // We have to copy the argument onto the heap in case the - // function hangs onto the reflect.Value we pass it. - p := unsafe_New(rt) - memmove(p, unsafe.Pointer(ap), rt.size) - - v := Value{rt, p, flag(rt.Kind()) | flagIndir} - in = append(in, v) - ap += rt.size - ap = align(ap, s390_arch_stack_slot_align) - - return in, ap -} - -// The s390_add_memarg function adds an argument passed in memory. -func s390_add_memarg(in []Value, ap uintptr, rt *rtype) ([]Value, uintptr) { - // If we're not already at the beginning of a stack slot, - // round up to the beginning of the next one. - ap = align(ap, s390_arch_stack_slot_align) - - // We have to copy the argument onto the heap in case the - // function hangs onto the reflect.Value we pass it. - p := unsafe_New(rt) - memmove(p, *(*unsafe.Pointer)(unsafe.Pointer(ap)), rt.size) - - v := Value{rt, p, flag(rt.Kind()) | flagIndir} - in = append(in, v) - ap += s390_arch_stack_slot_align - - return in, ap -} - -// The s390_general_reg_val function returns the value of integer register GR. -func s390_general_reg_val(regs *s390_regs, gr int) s390_arch_gr_t { - switch gr { - case 0: - return regs.r2 - case 1: - return regs.r3 - case 2: - return regs.r4 - case 3: - return regs.r5 - case 4: - return regs.r6 - default: - panic("s390_general_reg_val: bad integer register") - } -} - -// The s390_float_reg_val function returns the value of float register FR. -func s390_float_reg_val(regs *s390_regs, fr int) uintptr { - var r s390_arch_fr_t - switch fr { - case 0: - r = regs.f0 - case 1: - r = regs.f2 - default: - panic("s390_float_reg_val: bad floating point register") - } - return uintptr(r) -} diff --git a/libgo/go/reflect/makefuncgo_s390x.go b/libgo/go/reflect/makefuncgo_s390x.go deleted file mode 100644 index 6e510156b34..00000000000 --- a/libgo/go/reflect/makefuncgo_s390x.go +++ /dev/null @@ -1,436 +0,0 @@ -// Copyright 2014 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 s390x implementation. - -package reflect - -import "unsafe" - -// Convenience types and constants. -const s390x_arch_stack_slot_align uintptr = 8 -const s390x_num_gr = 5 -const s390x_num_fr = 4 - -type s390x_arch_gr_t uint64 -type s390x_arch_fr_t uint64 - -// The assembler stub will pass a pointer to this structure. -// This will come in holding all the registers that might hold -// function parameters. On return we will set the registers that -// might hold result values. -type s390x_regs struct { - r2 s390x_arch_gr_t - r3 s390x_arch_gr_t - r4 s390x_arch_gr_t - r5 s390x_arch_gr_t - r6 s390x_arch_gr_t - stack_args s390x_arch_gr_t - f0 s390x_arch_fr_t - f2 s390x_arch_fr_t - f4 s390x_arch_fr_t - f6 s390x_arch_fr_t -} - -// Argument classifications that arise for Go types. -type s390x_arg_t int - -const ( - s390x_general_reg s390x_arg_t = iota - s390x_float_reg - // Argument passed as a pointer to an in-memory value. - s390x_mem_ptr - s390x_empty -) - -// s390xClassifyParameter returns the register class needed to -// pass the value of type TYP. s390x_empty means the register is -// not used. The second and third return values are the offset of -// an rtype parameter passed in a register (second) or stack slot -// (third). -func s390xClassifyParameter(typ *rtype) (s390x_arg_t, uintptr, uintptr) { - offset := s390x_arch_stack_slot_align - typ.Size() - switch typ.Kind() { - default: - panic("internal error--unknown kind in s390xClassifyParameter") - case Bool, Int, Int8, Int16, Int32, Uint, Uint8, Uint16, Uint32: - return s390x_general_reg, offset, offset - case Int64, Uint64, Uintptr, Chan, Func, Map, Ptr, UnsafePointer: - return s390x_general_reg, 0, 0 - case Float32, Float64: - return s390x_float_reg, 0, offset - case Complex64, Complex128: - // Complex numbers are passed by reference. - return s390x_mem_ptr, 0, 0 - case Array, Struct: - var ityp *rtype - var length int - - if typ.Size() == 0 { - return s390x_empty, 0, 0 - } - switch typ.Size() { - default: - // Pointer to memory. - return s390x_mem_ptr, 0, 0 - case 1, 2: - // Pass in an integer register. - return s390x_general_reg, offset, offset - - case 4, 8: - // See below. - } - if typ.Kind() == Array { - atyp := (*arrayType)(unsafe.Pointer(typ)) - length = atyp.Len() - ityp = atyp.elem - } else { - styp := (*structType)(unsafe.Pointer(typ)) - length = len(styp.fields) - ityp = styp.fields[0].typ - } - if length == 1 { - class, off_reg, off_slot := s390xClassifyParameter(ityp) - if class == s390x_float_reg { - // The array (stored in a structure) or struct - // is "equivalent to a floating point type" as - // defined in the S390x Abi. Note that this - // can only be the case in the cases 4 and 8 of - // the switch above. - return s390x_float_reg, off_reg, off_slot - } - } - // Otherwise pass in an integer register. - switch typ.Size() { - case 4, 8: - return s390x_general_reg, offset, offset - default: - return s390x_general_reg, 0, 0 - } - case Interface, Slice, String: - return s390x_mem_ptr, 0, 0 - } -} - -// s390xClassifyReturn returns the register classes needed to -// return the value of type TYP. s390_empty means the register is -// not used. The second value is the offset of an rtype return -// parameter if stored in a register. -func s390xClassifyReturn(typ *rtype) (s390x_arg_t, uintptr) { - offset := s390x_arch_stack_slot_align - typ.Size() - switch typ.Kind() { - default: - panic("internal error--unknown kind in s390xClassifyReturn") - case Bool, Int, Int8, Int16, Int32, Int64, - Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: - - return s390x_general_reg, offset - case Chan, Func, Map, Ptr, UnsafePointer: - return s390x_general_reg, 0 - case Float32, Float64: - return s390x_float_reg, 0 - case Complex64, Complex128: - return s390x_mem_ptr, 0 - case Interface, Slice, String: - return s390x_mem_ptr, 0 - case Array, Struct: - if typ.size == 0 { - return s390x_empty, 0 - } - // No optimization is done for returned structures and arrays. - return s390x_mem_ptr, 0 - } -} - -// Given a value of type *rtype left aligned in an unsafe.Pointer, -// reload the value so that it can be stored in a general or -// floating point register. For general registers the value is -// sign extend and right aligned. -func s390xReloadForRegister(typ *rtype, w uintptr, offset uintptr) uintptr { - var do_sign_extend bool = false - var gr s390x_arch_gr_t - - switch typ.Kind() { - case Int, Int8, Int16, Int32, Int64: - do_sign_extend = true - default: - // Handle all other cases in the next switch. - } - switch typ.size { - case 1: - if do_sign_extend == true { - se := int64(*(*int8)(unsafe.Pointer(&w))) - gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&se)) - } else { - e := int64(*(*uint8)(unsafe.Pointer(&w))) - gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&e)) - } - case 2: - if do_sign_extend == true { - se := int64(*(*int16)(unsafe.Pointer(&w))) - gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&se)) - } else { - e := int64(*(*uint16)(unsafe.Pointer(&w))) - gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&e)) - } - case 4: - if do_sign_extend == true { - se := int64(*(*int32)(unsafe.Pointer(&w))) - gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&se)) - } else { - e := int64(*(*uint32)(unsafe.Pointer(&w))) - gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&e)) - } - default: - panic("reflect: bad size in s390xReloadForRegister") - } - - return *(*uintptr)(unsafe.Pointer(&gr)) -} - -// MakeFuncStubGo implements the s390x calling convention for -// MakeFunc. This should not be called. It is exported so that -// assembly code can call it. -func S390xMakeFuncStubGo(regs *s390x_regs, c *makeFuncImpl) { - ftyp := c.typ - gr := 0 - fr := 0 - ap := uintptr(regs.stack_args) - - // See if the result requires a struct. If it does, the first - // parameter is a pointer to the struct. - var ret_class s390x_arg_t - var ret_off_reg uintptr - var ret_type *rtype - - switch len(ftyp.out) { - case 0: - ret_type = nil - ret_class, ret_off_reg = s390x_empty, 0 - case 1: - ret_type = ftyp.out[0] - ret_class, ret_off_reg = s390xClassifyReturn(ret_type) - default: - ret_type = nil - ret_class, ret_off_reg = s390x_mem_ptr, 0 - } - in := make([]Value, 0, len(ftyp.in)) - if ret_class == s390x_mem_ptr { - // We are returning a value in memory, which means - // that the first argument is a hidden parameter - // pointing to that return area. - gr++ - } - -argloop: - for _, rt := range ftyp.in { - class, off_reg, off_slot := s390xClassifyParameter(rt) - fl := flag(rt.Kind()) - switch class { - case s390x_empty: - v := Value{rt, nil, fl | flagIndir} - in = append(in, v) - continue argloop - case s390x_general_reg: - // Values stored in a general register are right - // aligned. - if gr < s390x_num_gr { - val := s390x_general_reg_val(regs, gr) - iw := unsafe.Pointer(val) - k := rt.Kind() - if k != Ptr && k != UnsafePointer { - ix := uintptr(unsafe.Pointer(&val)) - ix += off_reg - iw = unsafe.Pointer(ix) - fl |= flagIndir - } - v := Value{rt, iw, fl} - in = append(in, v) - gr++ - } else { - in, ap = s390x_add_stackreg( - in, ap, rt, off_slot) - } - continue argloop - case s390x_float_reg: - // In a register, floats are left aligned, but in a - // stack slot they are right aligned. - if fr < s390x_num_fr { - val := s390x_float_reg_val(regs, fr) - ix := uintptr(unsafe.Pointer(&val)) - v := Value{ - rt, unsafe.Pointer(unsafe.Pointer(ix)), - fl | flagIndir, - } - in = append(in, v) - fr++ - } else { - in, ap = s390x_add_stackreg( - in, ap, rt, off_slot) - } - continue argloop - case s390x_mem_ptr: - if gr < s390x_num_gr { - // Register holding a pointer to memory. - val := s390x_general_reg_val(regs, gr) - v := Value{ - rt, unsafe.Pointer(val), fl | flagIndir} - in = append(in, v) - gr++ - } else { - // Stack slot holding a pointer to memory. - in, ap = s390x_add_memarg(in, ap, rt) - } - continue argloop - } - panic("reflect: argtype not handled in MakeFunc:argloop") - } - - // All the real arguments have been found and turned into - // Values. Call the real function. - - out := c.call(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") - } - } - - switch ret_class { - case s390x_general_reg, s390x_float_reg: - // Single return value in a general or floating point register. - v := out[0] - var w uintptr - switch v.Kind() { - case Ptr, UnsafePointer, Chan, Func, Map: - w = uintptr(v.pointer()) - default: - memmove(unsafe.Pointer(&w), v.ptr, v.typ.size) - if ret_off_reg != 0 { - w = s390xReloadForRegister( - ret_type, w, ret_off_reg) - } - } - if ret_class == s390x_float_reg { - regs.f0 = s390x_arch_fr_t(w) - } else { - regs.r2 = s390x_arch_gr_t(w) - } - - case s390x_mem_ptr: - // The address of the memory area was passed as a hidden - // parameter in %r2. Multiple return values are always returned - // in an in-memory structure. - ptr := unsafe.Pointer(uintptr(regs.r2)) - off := uintptr(0) - for i, typ := range ftyp.out { - v := out[i] - off = align(off, uintptr(typ.fieldAlign)) - addr := unsafe.Pointer(uintptr(ptr) + off) - if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) { - *(*unsafe.Pointer)(addr) = v.ptr - } else { - memmove(addr, v.ptr, typ.size) - } - off += typ.size - } - - case s390x_empty: - } - - return -} - -// The s390x_add_stackreg function adds an argument passed on the -// stack that could be passed in a register. -func s390x_add_stackreg(in []Value, ap uintptr, rt *rtype, offset uintptr) ([]Value, uintptr) { - // If we're not already at the beginning of a stack slot, round up to - // the beginning of the next one. - ap = align(ap, s390x_arch_stack_slot_align) - // If offset is > 0, the data is right aligned on the stack slot. - ap += offset - - // We have to copy the argument onto the heap in case the - // function hangs onto the reflect.Value we pass it. - p := unsafe_New(rt) - memmove(p, unsafe.Pointer(ap), rt.size) - - v := Value{rt, p, flag(rt.Kind()) | flagIndir} - in = append(in, v) - ap += rt.size - ap = align(ap, s390x_arch_stack_slot_align) - - return in, ap -} - -// The s390x_add_memarg function adds an argument passed in memory. -func s390x_add_memarg(in []Value, ap uintptr, rt *rtype) ([]Value, uintptr) { - // If we're not already at the beginning of a stack slot, - // round up to the beginning of the next one. - ap = align(ap, s390x_arch_stack_slot_align) - - // We have to copy the argument onto the heap in case the - // function hangs onto the reflect.Value we pass it. - p := unsafe_New(rt) - memmove(p, *(*unsafe.Pointer)(unsafe.Pointer(ap)), rt.size) - - v := Value{rt, p, flag(rt.Kind()) | flagIndir} - in = append(in, v) - ap += s390x_arch_stack_slot_align - - return in, ap -} - -// The s390x_general_reg_val function returns the value of integer register GR. -func s390x_general_reg_val(regs *s390x_regs, gr int) uintptr { - var r s390x_arch_gr_t - switch gr { - case 0: - r = regs.r2 - case 1: - r = regs.r3 - case 2: - r = regs.r4 - case 3: - r = regs.r5 - case 4: - r = regs.r6 - default: - panic("s390x_general_reg_val: bad integer register") - } - return uintptr(r) -} - -// The s390x_float_reg_val function returns the value of float register FR. -func s390x_float_reg_val(regs *s390x_regs, fr int) uintptr { - var r s390x_arch_fr_t - switch fr { - case 0: - r = regs.f0 - case 1: - r = regs.f2 - case 2: - r = regs.f4 - case 3: - r = regs.f6 - default: - panic("s390x_float_reg_val: bad floating point register") - } - return uintptr(r) -} diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go index 09210b37b70..7cc4f7f8bfd 100644 --- a/libgo/go/reflect/value.go +++ b/libgo/go/reflect/value.go @@ -308,9 +308,6 @@ func (v Value) CallSlice(in []Value) []Value { var callGC bool // for testing; see TestCallMethodJump -var makeFuncStubFn = makeFuncStub -var makeFuncStubCode = **(**uintptr)(unsafe.Pointer(&makeFuncStubFn)) - func (v Value) call(op string, in []Value) []Value { // Get function pointer, type. t := v.typ @@ -388,17 +385,6 @@ func (v Value) call(op string, in []Value) []Value { } nout := t.NumOut() - // If target is makeFuncStub, short circuit the unpack onto stack / - // pack back into []Value for the args and return values. Just do the - // call directly. - // We need to do this here because otherwise we have a situation where - // reflect.callXX calls makeFuncStub, neither of which knows the - // layout of the args. That's bad for precise gc & stack copying. - x := (*makeFuncImpl)(fn) - if x.code == makeFuncStubCode { - return x.call(in) - } - if v.flag&flagMethod != 0 { nin++ } @@ -1120,16 +1106,6 @@ func (v Value) Pointer() uintptr { case Chan, Map, Ptr, UnsafePointer: return uintptr(v.pointer()) case Func: - if v.flag&flagMethod != 0 { - // As the doc comment says, the returned pointer is an - // underlying code pointer but not necessarily enough to - // identify a single function uniquely. All method expressions - // created via reflect have the same underlying code pointer, - // so their Pointers are equal. The function used here must - // match the one used in makeMethodValue. - f := makeFuncStub - return **(**uintptr)(unsafe.Pointer(&f)) - } p := v.pointer() // Non-nil func value points at data block. // First word of data block is actual code. |