public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Ian Lance Taylor <iant@golang.org>
To: gcc-patches <gcc-patches@gcc.gnu.org>,
		gofrontend-dev <gofrontend-dev@googlegroups.com>
Subject: libgo patch committed: Promote integer closure return to full word for libffi
Date: Tue, 17 Sep 2019 20:24:00 -0000	[thread overview]
Message-ID: <CAOyqgcVTUofxPw7PLLBraMpXA-JM7nSvxj4ywUSDj6yVX2siiA@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 489 bytes --]

The libffi library expects an integer return type to be promoted to a
full word.  This patch to libgo implements that when returning from a
closure written in Go.  This only matters on big-endian systems when
returning an integer smaller than the pointer size, which is why we
didn't notice it until now.  This fixes GCC PR 91781.  Bootstrapped
and ran Go testsuite on x86_64-pc-linux-gnu.  Bootstrapped and ran
some of the libgo tests on powerpc64-linux-gnu.  Committed to
mainline.

Ian

[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 5046 bytes --]

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 275809)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@
-ff18e041624b8c23ffcd747f51e9dda945777d2a
+7aabaf8623cf88e2378057476a034093abbe5aab
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: libgo/go/reflect/makefunc_ffi.go
===================================================================
--- libgo/go/reflect/makefunc_ffi.go	(revision 275809)
+++ libgo/go/reflect/makefunc_ffi.go	(working copy)
@@ -28,7 +28,7 @@ func makeCIF(ft *funcType) unsafe.Pointe
 //
 // The ffi_callback handles __go_makefunc_can_recover, and
 // then passes off the data as received from ffi here.
-func ffiCallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFuncImpl) {
+func ffiCallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFuncImpl, wordsize int32, bigEndian bool) {
 	ftyp := impl.typ
 	in := make([]Value, 0, len(ftyp.in))
 	ap := params
@@ -42,21 +42,46 @@ func ffiCallbackGo(results unsafe.Pointe
 
 	out := impl.call(in)
 
-	off := uintptr(0)
-	for i, typ := range ftyp.out {
-		v := out[i]
+	checkValue := func(v Value, typ *rtype, addr unsafe.Pointer) {
 		if v.flag&flagRO != 0 {
 			panic("reflect: function created by MakeFunc using " + funcName(impl.fn) +
 				" returned value obtained from unexported field")
 		}
 
-		off = align(off, uintptr(typ.fieldAlign))
-		addr := unsafe.Pointer(uintptr(results) + off)
-
 		// Convert v to type typ if v is assignable to a variable
 		// of type t in the language spec.
 		// See issue 28761.
 		v = v.assignTo("reflect.MakeFunc", typ, addr)
+	}
+
+	// In libffi a single integer return value is always promoted
+	// to a full word. This only matters for integers whose size
+	// is less than the size of a full word. There is similar code
+	// in libgo/runtime/go-reflect-call.c.
+	if len(ftyp.out) == 1 {
+		typ := ftyp.out[0]
+		switch typ.Kind() {
+		case Bool, Int8, Int16, Int32, Uint8, Uint16, Uint32:
+			v := out[0]
+			checkValue(v, typ, nil)
+
+			if bigEndian {
+				results = unsafe.Pointer(uintptr(results) + uintptr(wordsize) - typ.size)
+			}
+
+			memmove(results, v.ptr, typ.size)
+			return
+		}
+	}
+
+	off := uintptr(0)
+	for i, typ := range ftyp.out {
+		v := out[i]
+
+		off = align(off, uintptr(typ.fieldAlign))
+		addr := unsafe.Pointer(uintptr(results) + off)
+
+		checkValue(v, typ, addr)
 
 		if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
 			*(*unsafe.Pointer)(addr) = v.ptr
Index: libgo/go/reflect/makefunc_ffi_c.c
===================================================================
--- libgo/go/reflect/makefunc_ffi_c.c	(revision 275809)
+++ libgo/go/reflect/makefunc_ffi_c.c	(working copy)
@@ -25,7 +25,8 @@ void makeFuncFFI(void *cif, void *impl)
    function ffiCall with the pointer to the arguments, the results area,
    and the closure structure.  */
 
-extern void ffiCallbackGo(void *result, void **args, ffi_go_closure *closure)
+extern void ffiCallbackGo(void *result, void **args, ffi_go_closure *closure,
+                          int32 wordsize, _Bool big_endian)
   __asm__ (GOSYM_PREFIX "reflect.ffiCallbackGo");
 
 extern void makefuncfficanrecover(Slice)
@@ -72,7 +73,8 @@ ffi_callback (ffi_cif* cif __attribute__
       makefuncfficanrecover (s);
     }
 
-  ffiCallbackGo(results, args, closure);
+  ffiCallbackGo(results, args, closure, sizeof(ffi_arg),
+                __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__);
 
   if (i < n)
     makefuncreturning ();
Index: libgo/runtime/go-reflect-call.c
===================================================================
--- libgo/runtime/go-reflect-call.c	(revision 275698)
+++ libgo/runtime/go-reflect-call.c	(working copy)
@@ -44,8 +44,8 @@ go_results_size (const struct functype *
 
   types = (const struct _type **) func->out.__values;
 
-  /* A single integer return value is always promoted to a full
-     word.  */
+  /* A single integer return value is always promoted to a full word.
+     There is similar code below and in libgo/go/reflect/makefunc_ffi.go.*/
   if (count == 1)
     {
       switch (types[0]->kind & kindMask)
@@ -57,8 +57,6 @@ go_results_size (const struct functype *
 	case kindUint8:
 	case kindUint16:
 	case kindUint32:
-	case kindInt:
-	case kindUint:
 	  return sizeof (ffi_arg);
 
 	default:
@@ -108,8 +106,8 @@ go_set_results (const struct functype *f
 
   types = (const struct _type **) func->out.__values;
 
-  /* A single integer return value is always promoted to a full
-     word.  */
+  /* A single integer return value is always promoted to a full word.
+     There is similar code above and in libgo/go/reflect/makefunc_ffi.go.*/
   if (count == 1)
     {
       switch (types[0]->kind & kindMask)
@@ -121,8 +119,6 @@ go_set_results (const struct functype *f
 	case kindUint8:
 	case kindUint16:
 	case kindUint32:
-	case kindInt:
-	case kindUint:
 	  {
 	    union
 	    {

                 reply	other threads:[~2019-09-17 20:24 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAOyqgcVTUofxPw7PLLBraMpXA-JM7nSvxj4ywUSDj6yVX2siiA@mail.gmail.com \
    --to=iant@golang.org \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=gofrontend-dev@googlegroups.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).