From ba64c7b8934fbd59a1d5bd370a4aaab4bf2d0ed2 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 28 Feb 2018 18:17:29 +0100 Subject: [PATCH] re PR target/52991 (attribute packed broken on mingw32?) PR target/52991 * stor-layout.c (update_alignment_for_field): For targetm.ms_bitfield_layout_p (rli->t), if !is_bitfield && !DECL_PACKED (field), do the alignment update, just use only desired_align instead of MAX (type_align, desired_align) as the alignment. (place_field): Don't do known_align < desired_align handling early if targetm.ms_bitfield_layout_p (rli->t) and rli->prev_field is non-NULL, instead do it after rli->prev_field handling and only if not within a bitfield word. For DECL_PACKED (field) use type_align of BITS_PER_UNIT. * gcc.dg/bf-ms-layout.c: Revert 2012-04-26 changes. * gcc.dg/bf-ms-layout-2.c: Revert 2012-02-23 changes. * gcc.dg/bf-ms-layout-4.c: New test. * gcc.dg/bf-ms-layout-5.c: New test. From-SVN: r258075 --- gcc/ChangeLog | 14 ++++++++ gcc/stor-layout.c | 50 ++++++++++++++++++++++----- gcc/testsuite/ChangeLog | 8 +++++ gcc/testsuite/gcc.dg/bf-ms-layout-2.c | 16 ++++----- gcc/testsuite/gcc.dg/bf-ms-layout-4.c | 43 +++++++++++++++++++++++ gcc/testsuite/gcc.dg/bf-ms-layout-5.c | 45 ++++++++++++++++++++++++ gcc/testsuite/gcc.dg/bf-ms-layout.c | 16 ++++----- 7 files changed, 168 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/bf-ms-layout-4.c create mode 100644 gcc/testsuite/gcc.dg/bf-ms-layout-5.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index aece6243bf3..5d3319c00f0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2018-02-28 Jakub Jelinek + + PR target/52991 + * stor-layout.c (update_alignment_for_field): For + targetm.ms_bitfield_layout_p (rli->t), if !is_bitfield + && !DECL_PACKED (field), do the alignment update, just use + only desired_align instead of MAX (type_align, desired_align) + as the alignment. + (place_field): Don't do known_align < desired_align handling + early if targetm.ms_bitfield_layout_p (rli->t) and rli->prev_field + is non-NULL, instead do it after rli->prev_field handling and + only if not within a bitfield word. For DECL_PACKED (field) + use type_align of BITS_PER_UNIT. + 2018-02-28 Eric Botcazou * config/aarch64/aarch64.c (aarch64_emit_probe_stack_range): Remove diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index a4eeff18ec0..81f75a5eb72 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -1038,7 +1038,7 @@ update_alignment_for_field (record_layout_info rli, tree field, the type, except that for zero-size bitfields this only applies if there was an immediately prior, nonzero-size bitfield. (That's the way it is, experimentally.) */ - if ((!is_bitfield && !DECL_PACKED (field)) + if (!is_bitfield || ((DECL_SIZE (field) == NULL_TREE || !integer_zerop (DECL_SIZE (field))) ? !DECL_PACKED (field) @@ -1047,7 +1047,10 @@ update_alignment_for_field (record_layout_info rli, tree field, && ! integer_zerop (DECL_SIZE (rli->prev_field))))) { unsigned int type_align = TYPE_ALIGN (type); - type_align = MAX (type_align, desired_align); + if (!is_bitfield && DECL_PACKED (field)) + type_align = desired_align; + else + type_align = MAX (type_align, desired_align); if (maximum_field_alignment != 0) type_align = MIN (type_align, maximum_field_alignment); rli->record_align = MAX (rli->record_align, type_align); @@ -1303,7 +1306,9 @@ place_field (record_layout_info rli, tree field) /* Does this field automatically have alignment it needs by virtue of the fields that precede it and the record's own alignment? */ - if (known_align < desired_align) + if (known_align < desired_align + && (! targetm.ms_bitfield_layout_p (rli->t) + || rli->prev_field == NULL)) { /* No, we need to skip space before this field. Bump the cumulative size to multiple of field alignment. */ @@ -1331,8 +1336,6 @@ place_field (record_layout_info rli, tree field) if (! TREE_CONSTANT (rli->offset)) rli->offset_align = desired_align; - if (targetm.ms_bitfield_layout_p (rli->t)) - rli->prev_field = NULL; } /* Handle compatibility with PCC. Note that if the record has any @@ -1448,6 +1451,8 @@ place_field (record_layout_info rli, tree field) /* This is a bitfield if it exists. */ if (rli->prev_field) { + bool realign_p = known_align < desired_align; + /* If both are bitfields, nonzero, and the same size, this is the middle of a run. Zero declared size fields are special and handled as "end of run". (Note: it's nonzero declared @@ -1481,7 +1486,10 @@ place_field (record_layout_info rli, tree field) rli->remaining_in_alignment = typesize - bitsize; } else - rli->remaining_in_alignment -= bitsize; + { + rli->remaining_in_alignment -= bitsize; + realign_p = false; + } } else { @@ -1512,6 +1520,31 @@ place_field (record_layout_info rli, tree field) rli->prev_field = NULL; } + /* Does this field automatically have alignment it needs by virtue + of the fields that precede it and the record's own alignment? */ + if (realign_p) + { + /* If the alignment is still within offset_align, just align + the bit position. */ + if (desired_align < rli->offset_align) + rli->bitpos = round_up (rli->bitpos, desired_align); + else + { + /* First adjust OFFSET by the partial bits, then align. */ + tree d = size_binop (CEIL_DIV_EXPR, rli->bitpos, + bitsize_unit_node); + rli->offset = size_binop (PLUS_EXPR, rli->offset, + fold_convert (sizetype, d)); + rli->bitpos = bitsize_zero_node; + + rli->offset = round_up (rli->offset, + desired_align / BITS_PER_UNIT); + } + + if (! TREE_CONSTANT (rli->offset)) + rli->offset_align = desired_align; + } + normalize_rli (rli); } @@ -1530,7 +1563,7 @@ place_field (record_layout_info rli, tree field) if (!DECL_BIT_FIELD_TYPE (field) || (prev_saved != NULL ? !simple_cst_equal (TYPE_SIZE (type), TYPE_SIZE (prev_type)) - : !integer_zerop (DECL_SIZE (field)) )) + : !integer_zerop (DECL_SIZE (field)))) { /* Never smaller than a byte for compatibility. */ unsigned int type_align = BITS_PER_UNIT; @@ -1555,7 +1588,8 @@ place_field (record_layout_info rli, tree field) } /* Now align (conventionally) for the new type. */ - type_align = TYPE_ALIGN (TREE_TYPE (field)); + if (! DECL_PACKED (field)) + type_align = TYPE_ALIGN (TREE_TYPE (field)); if (maximum_field_alignment != 0) type_align = MIN (type_align, maximum_field_alignment); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 14b666d5df9..090d55bf9cf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2018-02-28 Jakub Jelinek + + PR target/52991 + * gcc.dg/bf-ms-layout.c: Revert 2012-04-26 changes. + * gcc.dg/bf-ms-layout-2.c: Revert 2012-02-23 changes. + * gcc.dg/bf-ms-layout-4.c: New test. + * gcc.dg/bf-ms-layout-5.c: New test. + 2018-02-28 Peter Bergner PR target/83399 diff --git a/gcc/testsuite/gcc.dg/bf-ms-layout-2.c b/gcc/testsuite/gcc.dg/bf-ms-layout-2.c index 2d0215fbd52..519785a8235 100644 --- a/gcc/testsuite/gcc.dg/bf-ms-layout-2.c +++ b/gcc/testsuite/gcc.dg/bf-ms-layout-2.c @@ -158,27 +158,27 @@ int main(){ struct ten test_ten; #if defined (_TEST_MS_LAYOUT) || defined (_MSC_VER) - size_t exp_sizeof_one = 8; - size_t exp_sizeof_two = 12; + size_t exp_sizeof_one = 12; + size_t exp_sizeof_two = 16; size_t exp_sizeof_three =6; size_t exp_sizeof_four = 8; size_t exp_sizeof_five = 3; size_t exp_sizeof_six = 8; size_t exp_sizeof_seven = 3; - size_t exp_sizeof_eight = 2; + size_t exp_sizeof_eight = 4; size_t exp_sizeof_nine = 8; - size_t exp_sizeof_ten = 8; + size_t exp_sizeof_ten = 16; - unsigned char exp_one_c = 7; - unsigned char exp_two_c = 9; + unsigned char exp_one_c = 8; + unsigned char exp_two_c = 12; unsigned char exp_three_c = 4; unsigned char exp_four_c = 4; char exp_five_c = 2; char exp_six_c = 5; char exp_seven_c = 2; - char exp_eight_c = 1; + char exp_eight_c = 2; char exp_nine_c = 0; - char exp_ten_c = 1; + char exp_ten_c = 8; #else /* testing -mno-ms-bitfields */ diff --git a/gcc/testsuite/gcc.dg/bf-ms-layout-4.c b/gcc/testsuite/gcc.dg/bf-ms-layout-4.c new file mode 100644 index 00000000000..821db075a9a --- /dev/null +++ b/gcc/testsuite/gcc.dg/bf-ms-layout-4.c @@ -0,0 +1,43 @@ +/* PR target/52991 */ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ + +#define CHECK(expr) extern char c[(expr) ? 1 : -1] +#define offsetof(x, y) __builtin_offsetof (x, y) + +struct test_sp1 { + int a; + short b; + int c; + char d; +} __attribute__((packed,ms_struct)); + +CHECK (sizeof (struct test_sp1) == 11); +CHECK (offsetof (struct test_sp1, a) == 0); +CHECK (offsetof (struct test_sp1, b) == 4); +CHECK (offsetof (struct test_sp1, c) == 6); +CHECK (offsetof (struct test_sp1, d) == 10); + +struct test_sp3 { + int a; + short b __attribute__((aligned(8))); + int c; + char d; +} __attribute__((packed,ms_struct)); + +CHECK (sizeof (struct test_sp3) == 16); +CHECK (offsetof (struct test_sp3, a) == 0); +CHECK (offsetof (struct test_sp3, b) == 8); +CHECK (offsetof (struct test_sp3, c) == 10); +CHECK (offsetof (struct test_sp3, d) == 14); + +struct test_s4 { + int a; + short b; + int c:15; + char d; +} __attribute__((ms_struct)); + +CHECK (sizeof (struct test_s4) == 16); +CHECK (offsetof (struct test_s4, a) == 0); +CHECK (offsetof (struct test_s4, b) == 4); +CHECK (offsetof (struct test_s4, d) == 12); diff --git a/gcc/testsuite/gcc.dg/bf-ms-layout-5.c b/gcc/testsuite/gcc.dg/bf-ms-layout-5.c new file mode 100644 index 00000000000..361b91464db --- /dev/null +++ b/gcc/testsuite/gcc.dg/bf-ms-layout-5.c @@ -0,0 +1,45 @@ +/* PR target/52991 */ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ + +struct S { + int a : 2; + __attribute__((aligned (8))) int b : 2; + int c : 28; + __attribute__((aligned (16))) int d : 2; + int e : 30; +} __attribute__((ms_struct)); + +struct S s; + +int +main () +{ + int i; + if (sizeof (s) != 32) + __builtin_abort (); + s.a = -1; + for (i = 0; i < 32; ++i) + if (((char *) &s)[i] != (i ? 0 : 3)) + __builtin_abort (); + s.a = 0; + s.b = -1; + for (i = 0; i < 32; ++i) + if (((char *) &s)[i] != (i ? 0 : 12)) + __builtin_abort (); + s.b = 0; + s.c = -1; + for (i = 0; i < 32; ++i) + if (((signed char *) &s)[i] != (i > 3 ? 0 : (i ? -1 : -16))) + __builtin_abort (); + s.c = 0; + s.d = -1; + for (i = 0; i < 32; ++i) + if (((signed char *) &s)[i] != (i == 16 ? 3 : 0)) + __builtin_abort (); + s.d = 0; + s.e = -1; + for (i = 0; i < 32; ++i) + if (((signed char *) &s)[i] != ((i < 16 || i > 19) ? 0 : (i == 16 ? -4 : -1))) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/bf-ms-layout.c b/gcc/testsuite/gcc.dg/bf-ms-layout.c index 92af9120723..94827516f93 100644 --- a/gcc/testsuite/gcc.dg/bf-ms-layout.c +++ b/gcc/testsuite/gcc.dg/bf-ms-layout.c @@ -153,27 +153,27 @@ int main(){ struct ten test_ten; #if defined (_TEST_MS_LAYOUT) || defined (_MSC_VER) - size_t exp_sizeof_one = 8; - size_t exp_sizeof_two = 12; + size_t exp_sizeof_one = 12; + size_t exp_sizeof_two = 16; size_t exp_sizeof_three =6; size_t exp_sizeof_four = 8; size_t exp_sizeof_five = 3; size_t exp_sizeof_six = 8; size_t exp_sizeof_seven = 3; - size_t exp_sizeof_eight = 2; + size_t exp_sizeof_eight = 4; size_t exp_sizeof_nine = 8; - size_t exp_sizeof_ten = 8; + size_t exp_sizeof_ten = 16; - unsigned char exp_one_c = 7; - unsigned char exp_two_c = 9; + unsigned char exp_one_c = 8; + unsigned char exp_two_c = 12; unsigned char exp_three_c = 4; unsigned char exp_four_c = 4; char exp_five_c = 2; char exp_six_c = 5; char exp_seven_c = 2; - char exp_eight_c = 1; + char exp_eight_c = 2; char exp_nine_c = 0; - char exp_ten_c = 1; + char exp_ten_c = 8; #else /* testing -mno-ms-bitfields */ -- 2.30.2