summaryrefslogtreecommitdiff
path: root/libgo/go/reflect
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2015-01-16 14:58:53 -0800
committerIan Lance Taylor <ian@gcc.gnu.org>2015-01-16 22:58:53 +0000
commit38bf819a5f995ae4621496df2324d68b9e24900f (patch)
treec90d2bfba44756e26640c50ad1389375693ef832 /libgo/go/reflect
parent21cb351825d45c42e9e5148715a2fd2051cf4ed1 (diff)
downloadgcc-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.go61
-rw-r--r--libgo/go/reflect/makefunc_386.S230
-rw-r--r--libgo/go/reflect/makefunc_amd64.S177
-rw-r--r--libgo/go/reflect/makefunc_dummy.c15
-rw-r--r--libgo/go/reflect/makefunc_ffi.go67
-rw-r--r--libgo/go/reflect/makefunc_ffi_c.c68
-rw-r--r--libgo/go/reflect/makefunc_s390.c86
-rw-r--r--libgo/go/reflect/makefuncgo_386.go139
-rw-r--r--libgo/go/reflect/makefuncgo_amd64.go496
-rw-r--r--libgo/go/reflect/makefuncgo_s390.go454
-rw-r--r--libgo/go/reflect/makefuncgo_s390x.go436
-rw-r--r--libgo/go/reflect/value.go24
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(&regs, 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" (&regs.r2) : "r2" );
- asm volatile ("ld\t%%f0,0(%0)" : : "a" (&regs.f0) : "f0" );
- } else {
- asm volatile ("l\t%%r2,0(%0)" : : "a" (&regs.r2) : "r2" );
- asm volatile ("l\t%%r3,0(%0)" : : "a" (&regs.r3) : "r3" );
- asm volatile ("ld\t%%f0,0(%0)" : : "a" (&regs.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(&regs.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(&reg)
- 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(&reg), 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.