]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gimple: Handle tail padding when computing gimple_ops_offset
authorLewis Hyatt <lhyatt@gmail.com>
Tue, 29 Oct 2024 20:57:12 +0000 (16:57 -0400)
committerLewis Hyatt <lhyatt@gcc.gnu.org>
Sat, 23 Nov 2024 18:44:38 +0000 (13:44 -0500)
The array gimple_ops_offset_[], which is used to find the trailing op[]
array for a given gimple struct, is computed assuming that op[] will be
found at sizeof(tree) bytes away from the end of the struct. This is only
correct if the alignment requirement of a pointer is the same as the
alignment requirement of the struct, otherwise there will be padding bytes
that invalidate the calculation. On 64-bit platforms, this generally works
fine because a pointer has 8-byte alignment and none of the structs make use
of more than that. On 32-bit platforms, it also currently works fine because
there are no 64-bit integers in the gimple structs. There are 32-bit
platforms (e.g. sparc) on which a pointer has 4-byte alignment and a
uint64_t has 8-byte alignment. On such platforms, adding a uint64_t to the
gimple structs (as will take place when location_t is changed to be 64-bit)
causes gimple_ops_offset_ to be 4 bytes too large.

It would be nice to use offsetof() to compute the offset exactly, but
offsetof() is not guaranteed to work for these types, because they use
inheritance and so are not standard layout types. This patch attempts to
detect the presence of tail padding by detecting when such padding is reused
by inheritance; the padding should generally be reused for the same reason
that offsetof() is not available, namely that all the relevant types use
inheritance. One could envision systems on which this fix does not go far
enough (e.g., if the ABI forbids reuse of tail padding), but it makes things
better without affecting anything that currently works.

gcc/ChangeLog:

* gimple.cc (get_tail_padding_adjustment): New function.
(DEFGSSTRUCT): Adjust the computation of gimple_ops_offset_ to be
correct in the presence of tail padding.

gcc/gimple.cc

index b31c8dc9b716321aa67c70aa61ab65c157ed1d95..c6d0991ded90098bddce8090e1d3bb19466da2b6 100644 (file)
@@ -51,12 +51,36 @@ along with GCC; see the file COPYING3.  If not see
 #include "ipa-modref.h"
 #include "dbgcnt.h"
 
-/* All the tuples have their operand vector (if present) at the very bottom
-   of the structure.  Therefore, the offset required to find the
-   operands vector the size of the structure minus the size of the 1
-   element tree array at the end (see gimple_ops).  */
+/* All the tuples have their operand vector (if present) at the very bottom of
+   the structure.  Therefore, the offset required to find the operands vector is
+   the size of the structure minus the size of the 1-element tree array at the
+   end (see gimple_ops).  An adjustment may be required if there is tail
+   padding, as may happen on a host (e.g. sparc) where a pointer has 4-byte
+   alignment while a uint64_t has 8-byte alignment.
+
+   Unfortunately, we can't use offsetof to do this computation 100%
+   straightforwardly, because these structs use inheritance and so are not
+   standard layout types.  However, the fact that they are not standard layout
+   types also means that tail padding will be reused in inheritance, which makes
+   it possible to check for the problematic case with the following logic
+   instead.  If tail padding is detected, the offset should be decreased
+   accordingly.  */
+
+template<typename G>
+static constexpr size_t
+get_tail_padding_adjustment ()
+{
+  struct padding_check : G
+  {
+    tree t;
+  };
+  return sizeof (padding_check) == sizeof (G) ? sizeof (tree) : 0;
+}
+
 #define DEFGSSTRUCT(SYM, STRUCT, HAS_TREE_OP) \
-       (HAS_TREE_OP ? sizeof (struct STRUCT) - sizeof (tree) : 0),
+  (HAS_TREE_OP \
+   ? sizeof (STRUCT) - sizeof (tree) - get_tail_padding_adjustment<STRUCT> () \
+   : 0),
 EXPORTED_CONST size_t gimple_ops_offset_[] = {
 #include "gsstruct.def"
 };