reflect: Fix MakeFunc returning float32 or float64 on 386.

From-SVN: r205932
This commit is contained in:
Ian Lance Taylor 2013-12-12 17:44:01 +00:00
parent c9846a8c52
commit ea56ff71a4
2 changed files with 26 additions and 15 deletions

View File

@ -25,8 +25,9 @@ reflect.makeFuncStub:
struct {
esp uint32 // 0x0
eax uint32 // 0x4
st0 uint64 // 0x8
sr int32 // 0x10
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
@ -84,6 +85,10 @@ reflect.makeFuncStub:
/* Set return registers. */
movl -20(%ebp), %eax
cmpb $0, -7(%ebp)
je 2f
fldl -16(%ebp)
#ifdef __SSE2__
@ -92,7 +97,8 @@ reflect.makeFuncStub:
movsd -16(%ebp), %xmm0
#endif
movl -8(%ebp), %edx
2:
movb -8(%ebp), %dl
addl $36, %esp
popl %ebx
@ -100,7 +106,7 @@ reflect.makeFuncStub:
popl %ebp
.LCFI4:
testl %edx,%edx
testb %dl,%dl
jne 1f
ret
1:

View File

@ -14,9 +14,10 @@ import "unsafe"
// registers that might hold result values.
type i386Regs struct {
esp uint32
eax uint32 // Value to return in %eax.
st0 uint64 // Value to return in %st(0).
sr int32 // Set to non-zero if hidden struct pointer.
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.
@ -57,12 +58,13 @@ func MakeFuncStubGo(regs *i386Regs, c *makeFuncImpl) {
in := make([]Value, 0, len(ftyp.in))
ap := uintptr(regs.esp)
regs.sr = 0
regs.sr = false
regs.sf = false
var retPtr unsafe.Pointer
if retStruct {
retPtr = *(*unsafe.Pointer)(unsafe.Pointer(ap))
ap += ptrSize
regs.sr = 1
regs.sr = true
}
for _, rt := range ftyp.in {
@ -126,13 +128,16 @@ func MakeFuncStubGo(regs *i386Regs, c *makeFuncImpl) {
v := out[0]
w := v.iword()
if v.Kind() != Ptr && v.Kind() != UnsafePointer {
w = loadIword(unsafe.Pointer(w), v.typ.size)
}
switch v.Kind() {
case Float32, Float64:
regs.st0 = uint64(uintptr(w))
default:
case Ptr, UnsafePointer:
regs.eax = uint32(uintptr(w))
case Float32:
regs.st0 = float64(*(*float32)(unsafe.Pointer(w)))
regs.sf = true
case Float64:
regs.st0 = *(*float64)(unsafe.Pointer(w))
regs.sf = true
default:
regs.eax = uint32(uintptr(loadIword(unsafe.Pointer(w), v.typ.size)))
}
}