From 50143b85bd90a2e06c0dd192a966574a3279c463 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 23 May 2023 10:15:35 +0200 Subject: [PATCH] Fix handling of non-integral bit-fields in native_encode_initializer 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 gcc/ * fold-const.cc (native_encode_initializer) : 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. gcc/testsuite/ * gnat.dg/opt101.adb: New test. * gnat.dg/opt101_pkg.ads: New helper. --- gcc/fold-const.cc | 27 +++++++++++++++++---------- gcc/testsuite/gnat.dg/opt101.adb | 23 +++++++++++++++++++++++ gcc/testsuite/gnat.dg/opt101_pkg.ads | 26 ++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/opt101.adb create mode 100644 gcc/testsuite/gnat.dg/opt101_pkg.ads diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 25466e97220..57521501fff 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -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) diff --git a/gcc/testsuite/gnat.dg/opt101.adb b/gcc/testsuite/gnat.dg/opt101.adb new file mode 100644 index 00000000000..68773bbad40 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt101.adb @@ -0,0 +1,23 @@ +-- { dg-do run } +-- { dg-options "-O" } + +pragma Optimize_Alignment (Space); + +with Opt101_Pkg; use Opt101_Pkg; + +procedure Opt101 is + + C1 : Cont1; + C2 : Cont2; + +begin + C1 := ((1234, 1, 2), 1, 2); + if C1.R.I1 /= 1 or C1.I2 /= 2 then + raise Program_Error; + end if; + + C2 := (1, (1234, 1, 2), 2); + if C2.R.I1 /= 1 or C2.I2 /= 2 then + raise Program_Error; + end if; +end; diff --git a/gcc/testsuite/gnat.dg/opt101_pkg.ads b/gcc/testsuite/gnat.dg/opt101_pkg.ads new file mode 100644 index 00000000000..0c843dfe335 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt101_pkg.ads @@ -0,0 +1,26 @@ +package Opt101_Pkg is + + type Int is mod 16; + + type Rec is record + S : Short_Integer; + I1, I2 : Int; + end record; + pragma Pack (Rec); + for Rec'Alignment use 4; + + type Cont1 is record + R : Rec; + I1, I2 : Int; + end record; + pragma Pack (Cont1); + + type Cont2 is record + I1 : Int; + R : Rec; + I2 : Int; + end record; + pragma Pack (Cont2); + pragma No_Component_Reordering (Cont2); + +end Opt101_Pkg; -- 2.11.4.GIT