This patch to the Go frontend, libgo, and the -fgo-dump-spec code
avoids padding incorrectly when a zero-sized field is inserted solely
for alignment.  We avoid this by not padding after a "_" field, and by
using "_" fields for padding.  This is fine since the padding is only
there in case someone takes the address of the last field, and it's
not possible to take the adress of a field named "_".  This was
breaking the use of epoll on sparc64 GNU/Linux, as reported in GCC PR
103847.  Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu,
bootstrapped and ran relevant tests on sparc64-unknown-linux-gnu.
Committed to mainline.

Ian



PR go/103847
* godump.c (go_force_record_alignment): Name the alignment
field "_".
fff15be41ed94c07c94ca5203b23b60e1b628e5c
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 05e47ec3fa9..2d04f4b01c0 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-3e9f4ee16683883ccfb8661d99318c74bb7a4bef
+d3be41f0a1fca20e241e1db62b4b0f5262caac55
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 0f66661937c..57c02a97ef0 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -6454,9 +6454,18 @@ get_backend_struct_fields(Gogo* gogo, Struct_type* type, 
bool use_placeholder,
                             ? p->type()->get_backend_placeholder(gogo)
                             : p->type()->get_backend(gogo));
       (*bfields)[i].location = p->location();
-      lastsize = gogo->backend()->type_size((*bfields)[i].btype);
-      if (lastsize != 0)
-        saw_nonzero = true;
+      int64_t size = gogo->backend()->type_size((*bfields)[i].btype);
+      if (size != 0)
+       saw_nonzero = true;
+
+      if (size > 0 || !Gogo::is_sink_name(p->field_name()))
+       lastsize = size;
+      else
+       {
+         // There is an unreferenceable field of zero size.  This
+         // doesn't affect whether we may need zero padding, so leave
+         // lastsize unchanged.
+       }
     }
   go_assert(i == fields->size());
   if (saw_nonzero && lastsize == 0 && !type->is_results_struct())
diff --git a/gcc/godump.c b/gcc/godump.c
index a50aef1f5fa..f016989c93f 100644
--- a/gcc/godump.c
+++ b/gcc/godump.c
@@ -651,7 +651,7 @@ go_force_record_alignment (struct obstack *ob, const char 
*type_string,
                           unsigned int index, const char *error_string)
 {
   index = go_append_artificial_name (ob, index);
-  obstack_grow (ob, "_align ", 7);
+  obstack_grow (ob, "_ ", 2);
   if (type_string == NULL)
     obstack_grow (ob, error_string, strlen (error_string));
   else
diff --git a/libgo/mkrsysinfo.sh b/libgo/mkrsysinfo.sh
index 18643370645..be150905f91 100755
--- a/libgo/mkrsysinfo.sh
+++ b/libgo/mkrsysinfo.sh
@@ -98,7 +98,7 @@ if grep '^const _epoll_data_offset ' ${OUT} >/dev/null 2>&1; 
then
       echo 'type epollevent struct { events uint32; data [8]byte }' >> ${OUT}
   elif test "$val" = "8"; then
       if test "$GOARCH" = "sparc64" -a "$GOOS" = "linux"; then
-          echo 'type epollevent struct { events uint32; pad [4]byte; data 
[8]byte; _align [0]int64 }' >> ${OUT}
+          echo 'type epollevent struct { events uint32; pad [4]byte; data 
[8]byte; _ [0]int64 }' >> ${OUT}
       else
           echo 'type epollevent struct { events uint32; pad [4]byte; data 
[8]byte }' >> ${OUT}
       fi

Reply via email to