Fix handling of non-integral bit-fields in native_encode_initializer
Checks
Commit Message
Hi,
the encoder for CONSTRUCTORs assumes that all bit-fields (DECL_BIT_FIELD) have
integral types, but that's not the case in Ada where they may have pretty much
any type, resulting in a wrong encoding for them.
The attached fix filters out non-integral bit-fields, except if they start and
end on a byte boundary because they are correctly handled in this case.
Bootstrapped/regtested on x86-64/Linux, OK for mainline and 13 branch?
2023-05-22 Eric Botcazou <ebotcazou@adacore.com>
* fold-const.cc (native_encode_initializer) <CONSTRUCTOR>: Apply the
specific treatment for bit-fields only if they have an integral type
and filter out non-integral bit-fields that do not start and end on
a byte boundary.
2023-05-22 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/opt101.adb: New test.
* gnat.dg/opt101_pkg.ads: New helper.
Comments
On Mon, May 22, 2023 at 10:10 AM Eric Botcazou via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> Hi,
>
> the encoder for CONSTRUCTORs assumes that all bit-fields (DECL_BIT_FIELD) have
> integral types, but that's not the case in Ada where they may have pretty much
> any type, resulting in a wrong encoding for them.
>
> The attached fix filters out non-integral bit-fields, except if they start and
> end on a byte boundary because they are correctly handled in this case.
>
> Bootstrapped/regtested on x86-64/Linux, OK for mainline and 13 branch?
OK.
Can we handle non-integer bitfields by recursing with a temporary buffer to
encode it byte-aligned and then apply shifting and masking to get it in place?
Or is that not worth it?
Thanks,
Richard.
>
>
> 2023-05-22 Eric Botcazou <ebotcazou@adacore.com>
>
> * fold-const.cc (native_encode_initializer) <CONSTRUCTOR>: Apply the
> specific treatment for bit-fields only if they have an integral type
> and filter out non-integral bit-fields that do not start and end on
> a byte boundary.
>
>
> 2023-05-22 Eric Botcazou <ebotcazou@adacore.com>
>
> * gnat.dg/opt101.adb: New test.
> * gnat.dg/opt101_pkg.ads: New helper.
>
> --
> Eric Botcazou
> OK.
Thanks!
> Can we handle non-integer bitfields by recursing with a temporary buffer to
> encode it byte-aligned and then apply shifting and masking to get it in
> place? Or is that not worth it?
Certainly doable, something along these lines is implemented in varasm.c to
output these non-integral bit-fields (output_constructor et al) so we could
even try to share some code. However, in practice, these cases turn out to be
rare because the tree_output_constant_def path in gimplify_init_constructor is
well guarded.
@@ -8360,20 +8360,26 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
if (fieldsize == 0)
continue;
+ /* Prepare to deal with integral bit-fields and filter out other
+ bit-fields that do not start and end on a byte boundary. */
if (DECL_BIT_FIELD (field))
{
if (!tree_fits_uhwi_p (DECL_FIELD_BIT_OFFSET (field)))
return 0;
- fieldsize = TYPE_PRECISION (TREE_TYPE (field));
bpos = tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field));
- if (bpos % BITS_PER_UNIT)
- bpos %= BITS_PER_UNIT;
- else
- bpos = 0;
- fieldsize += bpos;
- epos = fieldsize % BITS_PER_UNIT;
- fieldsize += BITS_PER_UNIT - 1;
- fieldsize /= BITS_PER_UNIT;
+ if (INTEGRAL_TYPE_P (TREE_TYPE (field)))
+ {
+ bpos %= BITS_PER_UNIT;
+ fieldsize = TYPE_PRECISION (TREE_TYPE (field)) + bpos;
+ epos = fieldsize % BITS_PER_UNIT;
+ fieldsize += BITS_PER_UNIT - 1;
+ fieldsize /= BITS_PER_UNIT;
+ }
+ else if (bpos % BITS_PER_UNIT
+ || DECL_SIZE (field) == NULL_TREE
+ || !tree_fits_shwi_p (DECL_SIZE (field))
+ || tree_to_shwi (DECL_SIZE (field)) % BITS_PER_UNIT)
+ return 0;
}
if (off != -1 && pos + fieldsize <= off)
@@ -8382,7 +8388,8 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
if (val == NULL_TREE)
continue;
- if (DECL_BIT_FIELD (field))
+ if (DECL_BIT_FIELD (field)
+ && INTEGRAL_TYPE_P (TREE_TYPE (field)))
{
/* FIXME: Handle PDP endian. */
if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)