On Sun, Nov 17, 2024 at 4:25 AM Lewis Hyatt <lhy...@gmail.com> wrote:
>
> 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 | 34 +++++++++++++++++++++++++++++-----
>  1 file changed, 29 insertions(+), 5 deletions(-)
>
> diff --git a/gcc/gimple.cc b/gcc/gimple.cc
> index f7b313be40e..f0a642f5b51 100644
> --- a/gcc/gimple.cc
> +++ b/gcc/gimple.cc
> @@ -52,12 +52,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),

I wonder if we cannot simply use offsetof (STRUCT, ops) and some
"trick" to avoid
parsing/sanitizing this when HAS_TREE_OP is false?  Maybe even a

template <class T, bool has_offset>
constexpr size_t ops_offset () { return 0; }

template <class T>
constexpr size_t ops_offset<T, true> ()
{
  return offsetof (T, ops);
/* or T x; return (char *)x.ops - (char *)x; */
}

?  That is I don't like the "indirect" adjustment via computing the padding.

Richard.

>  EXPORTED_CONST size_t gimple_ops_offset_[] = {
>  #include "gsstruct.def"
>  };

Reply via email to