1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // MakeFunc 386 implementation.
11 // The assembler stub will pass a pointer to this structure. We
12 // assume that no parameters are passed in registers--that is, we do
13 // not support the -mregparm option. On return we will set the
14 // registers that might hold result values.
15 type i386Regs
struct {
17 eax
uint32 // Value to return in %eax.
18 st0
float64 // Value to return in %st(0).
19 sr
bool // Set to true if hidden struct pointer.
20 sf
bool // Set to true if returning float
23 // MakeFuncStubGo implements the 386 calling convention for MakeFunc.
24 // This should not be called. It is exported so that assembly code
27 func MakeFuncStubGo(regs
*i386Regs
, c
*makeFuncImpl
) {
30 // See if the result requires a struct. If it does, the first
31 // parameter is a pointer to the struct.
34 switch len(ftyp
.out
) {
38 if ftyp
.out
[0].size
== 0 {
41 switch ftyp
.out
[0].Kind() {
42 case Complex64
, Complex128
, Array
, Interface
, Slice
, String
, Struct
:
48 for _
, typ
:= range ftyp
.out
{
58 in
:= make([]Value
, 0, len(ftyp
.in
))
59 ap
:= uintptr(regs
.esp
)
63 var retPtr unsafe
.Pointer
65 retPtr
= *(*unsafe
.Pointer
)(unsafe
.Pointer(ap
))
70 for _
, rt
:= range ftyp
.in
{
71 ap
= align(ap
, ptrSize
)
73 // We have to copy the argument onto the heap in case
74 // the function hangs on the reflect.Value we pass it.
76 memmove(p
, unsafe
.Pointer(ap
), rt
.size
)
78 v
:= Value
{rt
, p
, flag(rt
.Kind()<<flagKindShift
) | flagIndir
}
83 // Call the real function.
87 if len(out
) != len(ftyp
.out
) {
88 panic("reflect: wrong return count from function created by MakeFunc")
91 for i
, typ
:= range ftyp
.out
{
94 panic("reflect: function created by MakeFunc using " + funcName(c
.fn
) +
95 " returned wrong type: have " +
96 out
[i
].typ
.String() + " for " + typ
.String())
98 if v
.flag
&flagRO
!= 0 {
99 panic("reflect: function created by MakeFunc using " + funcName(c
.fn
) +
100 " returned value obtained from unexported field")
110 for i
, typ
:= range ftyp
.out
{
112 off
= align(off
, uintptr(typ
.fieldAlign
))
113 addr
:= unsafe
.Pointer(uintptr(retPtr
) + off
)
114 if v
.flag
&flagIndir
== 0 && (v
.kind() == Ptr || v
.kind() == UnsafePointer
) {
115 storeIword(addr
, iword(v
.val
), typ
.size
)
117 memmove(addr
, v
.val
, typ
.size
)
121 regs
.eax
= uint32(uintptr(retPtr
))
125 if len(ftyp
.out
) != 1 {
126 panic("inconsistency")
132 case Ptr
, UnsafePointer
:
133 regs
.eax
= uint32(uintptr(w
))
135 regs
.st0
= float64(*(*float32)(unsafe
.Pointer(w
)))
138 regs
.st0
= *(*float64)(unsafe
.Pointer(w
))
141 regs
.eax
= uint32(uintptr(loadIword(unsafe
.Pointer(w
), v
.typ
.size
)))