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