On 386 when a function returns a struct the pointer to the return value
is passed as a hidden first parameter, and the function is supposed to
"ret 4" to pop the hidden parameter when returning to the caller.  The
implementation of reflect.MakeFunc in libgo was not doing that.  This
patch fixes the problem.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu, in both 32-bit and 64-bit mode.  Committed to
mainline and 4.8 branch.

Ian

diff -r fa6c22b293e8 libgo/go/reflect/makefunc_386.S
--- a/libgo/go/reflect/makefunc_386.S	Tue Nov 26 16:49:31 2013 -0800
+++ b/libgo/go/reflect/makefunc_386.S	Sat Nov 30 09:05:42 2013 -0800
@@ -26,8 +26,11 @@
 	     esp uint32		// 0x0
 	     eax uint32		// 0x4
 	     st0 uint64		// 0x8
+	     rs  int32		// 0x10
 	   }
-	*/
+	   The rs 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:
@@ -73,12 +76,19 @@
 	movsd	-16(%ebp), %xmm0
 #endif
 
+	movl	-8(%ebp), %edx
+
 	addl	$36, %esp
 	popl	%ebx
 .LCFI3:
 	popl	%ebp
 .LCFI4:
+
+	testl	%edx,%edx
+	jne	1f
 	ret
+1:
+	ret	$4
 .LFE1:
 #ifdef __ELF__
 	.size	reflect.makeFuncStub, . - reflect.makeFuncStub
diff -r fa6c22b293e8 libgo/go/reflect/makefuncgo_386.go
--- a/libgo/go/reflect/makefuncgo_386.go	Tue Nov 26 16:49:31 2013 -0800
+++ b/libgo/go/reflect/makefuncgo_386.go	Sat Nov 30 09:05:42 2013 -0800
@@ -16,6 +16,7 @@
 	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.
 }
 
 // MakeFuncStubGo implements the 386 calling convention for MakeFunc.
@@ -56,10 +57,12 @@
 	in := make([]Value, 0, len(ftyp.in))
 	ap := uintptr(regs.esp)
 
+	regs.sr = 0
 	var retPtr unsafe.Pointer
 	if retStruct {
 		retPtr = *(*unsafe.Pointer)(unsafe.Pointer(ap))
 		ap += ptrSize
+		regs.sr = 1
 	}
 
 	for _, rt := range ftyp.in {

Reply via email to