Rebase.
[official-gcc.git] / libgo / go / reflect / makefuncgo_386.go
blob7809fb01f2326494421f8789ca2d31f039d71413
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.
7 package reflect
9 import "unsafe"
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 {
16 esp uint32
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
25 // can call it.
27 func MakeFuncStubGo(regs *i386Regs, c *makeFuncImpl) {
28 ftyp := c.typ
30 // See if the result requires a struct. If it does, the first
31 // parameter is a pointer to the struct.
32 retStruct := false
33 retEmpty := false
34 switch len(ftyp.out) {
35 case 0:
36 retEmpty = true
37 case 1:
38 if ftyp.out[0].size == 0 {
39 retEmpty = true
40 } else {
41 switch ftyp.out[0].Kind() {
42 case Complex64, Complex128, Array, Interface, Slice, String, Struct:
43 retStruct = true
46 default:
47 size := uintptr(0)
48 for _, typ := range ftyp.out {
49 size += typ.size
51 if size == 0 {
52 retEmpty = true
53 } else {
54 retStruct = true
58 in := make([]Value, 0, len(ftyp.in))
59 ap := uintptr(regs.esp)
61 regs.sr = false
62 regs.sf = false
63 var retPtr unsafe.Pointer
64 if retStruct {
65 retPtr = *(*unsafe.Pointer)(unsafe.Pointer(ap))
66 ap += ptrSize
67 regs.sr = true
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.
75 p := unsafe_New(rt)
76 memmove(p, unsafe.Pointer(ap), rt.size)
78 v := Value{rt, p, flag(rt.Kind()<<flagKindShift) | flagIndir}
79 in = append(in, v)
80 ap += rt.size
83 // Call the real function.
85 out := c.call(in)
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 {
92 v := out[i]
93 if v.typ != typ {
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")
104 if retEmpty {
105 return
108 if retStruct {
109 off := uintptr(0)
110 for i, typ := range ftyp.out {
111 v := out[i]
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 *(*unsafe.Pointer)(addr) = v.ptr
116 } else {
117 memmove(addr, v.ptr, typ.size)
119 off += typ.size
121 regs.eax = uint32(uintptr(retPtr))
122 return
125 if len(ftyp.out) != 1 {
126 panic("inconsistency")
129 v := out[0]
130 switch v.Kind() {
131 case Ptr, UnsafePointer:
132 regs.eax = uint32(uintptr(v.pointer()))
133 case Float32:
134 regs.st0 = float64(*(*float32)(v.ptr))
135 regs.sf = true
136 case Float64:
137 regs.st0 = *(*float64)(v.ptr)
138 regs.sf = true
139 default:
140 regs.eax = uint32(loadScalar(v.ptr, v.typ.size))