diff options
Diffstat (limited to 'libgo/go/reflect/makefuncgo_386.go')
-rw-r--r-- | libgo/go/reflect/makefuncgo_386.go | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/libgo/go/reflect/makefuncgo_386.go b/libgo/go/reflect/makefuncgo_386.go new file mode 100644 index 00000000000..0fac1f488a4 --- /dev/null +++ b/libgo/go/reflect/makefuncgo_386.go @@ -0,0 +1,135 @@ +// 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 uint64 // Value to return in %st(0). +} + +// 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) + + var retPtr unsafe.Pointer + if retStruct { + retPtr = *(*unsafe.Pointer)(unsafe.Pointer(ap)) + ap += ptrSize + } + + 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()<<flagKindShift) | flagIndir} + in = append(in, v) + ap += rt.size + } + + // Call the real function. + + out := c.fn(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) { + storeIword(addr, iword(v.val), typ.size) + } else { + memmove(addr, v.val, typ.size) + } + off += typ.size + } + regs.eax = uint32(uintptr(retPtr)) + return + } + + if len(ftyp.out) != 1 { + panic("inconsistency") + } + + 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: + regs.eax = uint32(uintptr(w)) + } +} |