Go patch committed: Don't pad zero-sized trailing field in results struct

Message ID CAOyqgcV2BxkNVacUdGmVNmn7T2JgOT_nTGxxzLocVio_RsYFZw@mail.gmail.com
State New
Headers show
Series
  • Go patch committed: Don't pad zero-sized trailing field in results struct
Related show

Commit Message

Jakub Jelinek via Gcc-patches Sept. 11, 2021, 9:20 p.m.
This patch to the Go frontend avoids padding zero-sized trailing
fields in the struct created to hold result parameters.  This avoids a
miscompilation when a function returns multiple results and the last
result is zero-sized (this is not a useful way to write a function but
it can happen reasonably if on some targets the last result does have
a size).  Nothing can take the address of a field in a result struct,
so the padding is not required.  This fixes GCC PR 101994.
Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian
0d3eabf88aa766056f3e0061a7d369368629a451

Patch

diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index ff41af787b1..f4816816500 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@ 
-21b30eddc59d92a07264c3b21eb032d6c303d16f
+c11d9f8275f2bbe9b05cdd815c79ac331f78e15c
 
 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 e76600daab9..cd692506efc 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -5050,6 +5050,7 @@  Function_type::get_backend_fntype(Gogo* gogo)
 		  Struct_type* st = Type::make_struct_type(sfl,
 							   this->location());
 		  st->set_is_struct_incomparable();
+		  st->set_is_results_struct();
 		  ins.first->second = st->get_backend(gogo);
 		}
 	      bresult_struct = ins.first->second;
@@ -6458,7 +6459,7 @@  get_backend_struct_fields(Gogo* gogo, Struct_type* type, bool use_placeholder,
         saw_nonzero = true;
     }
   go_assert(i == fields->size());
-  if (saw_nonzero && lastsize == 0)
+  if (saw_nonzero && lastsize == 0 && !type->is_results_struct())
     {
       // For nonzero-sized structs which end in a zero-sized thing, we add
       // an extra byte of padding to the type. This padding ensures that
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index ca1ab49c57e..0c5180668ea 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -2501,7 +2501,8 @@  class Struct_type : public Type
   Struct_type(Struct_field_list* fields, Location location)
     : Type(TYPE_STRUCT),
       fields_(fields), location_(location), all_methods_(NULL),
-      is_struct_incomparable_(false), has_padding_(false)
+      is_struct_incomparable_(false), has_padding_(false),
+      is_results_struct_(false)
   { }
 
   // Return the field NAME.  This only looks at local fields, not at
@@ -2632,6 +2633,17 @@  class Struct_type : public Type
   set_has_padding()
   { this->has_padding_ = true; }
 
+  // Return whether this is a results struct created to hold the
+  // results of a function that returns multiple results.
+  bool
+  is_results_struct() const
+  { return this->is_results_struct_; }
+
+  // Record that this is a results struct.
+  void
+  set_is_results_struct()
+  { this->is_results_struct_ = true; }
+
   // Write the hash function for this type.
   void
   write_hash_function(Gogo*, Function_type*);
@@ -2742,6 +2754,9 @@  class Struct_type : public Type
   // True if this struct's backend type has padding, due to trailing
   // zero-sized field.
   bool has_padding_;
+  // True if this is a results struct created to hold the results of a
+  // function that returns multiple results.
+  bool is_results_struct_;
 };
 
 // The type of an array.