diff options
author | Sandra Loosemore <sandra@codesourcery.com> | 2019-12-01 22:52:15 -0500 |
---|---|---|
committer | Sandra Loosemore <sandra@gcc.gnu.org> | 2019-12-01 22:52:15 -0500 |
commit | 4569f8b3652ae1e5ca353c24148b50c786b36c8b (patch) | |
tree | f22f9ae555d8f38b980718893ef0bc8f71976ea5 | |
parent | e549dd44b5ff0547004a640554ebe55f1ce2936b (diff) | |
download | gcc-4569f8b3652ae1e5ca353c24148b50c786b36c8b.zip gcc-4569f8b3652ae1e5ca353c24148b50c786b36c8b.tar.gz gcc-4569f8b3652ae1e5ca353c24148b50c786b36c8b.tar.bz2 |
Fix bugs relating to flexibly-sized objects in nios2 backend.
2019-12-01 Sandra Loosemore <sandra@codesourcery.com>
Fix bugs relating to flexibly-sized objects in nios2 backend.
PR target/92499
gcc/c/
* c-decl.c (flexible_array_type_p): Move to common code.
gcc/
* config/nios2/nios2.c (nios2_in_small_data_p): Do not consider
objects of flexible types to be small if they have internal linkage
or are declared extern.
* config/nios2/nios2.h (ASM_OUTPUT_ALIGNED_LOCAL): Replace with...
(ASM_OUTPUT_ALIGNED_DECL_LOCAL): ...this. Use targetm.in_small_data_p
instead of the size of the object initializer.
* tree.c (flexible_array_type_p): Move from C front end, and
generalize to handle fields in non-C structures.
* tree.h (flexible_array_type_p): Declare.
gcc/testsuite/
* gcc.target/nios2/pr92499-1.c: New.
* gcc.target/nios2/pr92499-2.c: New.
* gcc.target/nios2/pr92499-3.c: New.
From-SVN: r278891
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/c/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/c/c-decl.c | 33 | ||||
-rw-r--r-- | gcc/config/nios2/nios2.c | 16 | ||||
-rw-r--r-- | gcc/config/nios2/nios2.h | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/nios2/pr92499-1.c | 48 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/nios2/pr92499-2.c | 45 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/nios2/pr92499-3.c | 23 | ||||
-rw-r--r-- | gcc/tree.c | 35 | ||||
-rw-r--r-- | gcc/tree.h | 1 |
11 files changed, 199 insertions, 36 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0b012af..9a807ba 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2019-12-01 Sandra Loosemore <sandra@codesourcery.com> + + PR target/92499 + + * config/nios2/nios2.c (nios2_in_small_data_p): Do not consider + objects of flexible types to be small if they have internal linkage + or are declared extern. + * config/nios2/nios2.h (ASM_OUTPUT_ALIGNED_LOCAL): Replace with... + (ASM_OUTPUT_ALIGNED_DECL_LOCAL): ...this. Use targetm.in_small_data_p + instead of the size of the object initializer. + * tree.c (flexible_array_type_p): Move from C front end, and + generalize to handle fields in non-C structures. + * tree.h (flexible_array_type_p): Declare. + 2019-11-30 Jan Hubicka <hubicka@ucw.cz> * profile-count.h (profile_count::operator<): Use IPA value for diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 8fee474..c04443e 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2019-12-01 Sandra Loosemore <sandra@codesourcery.com> + + PR target/92499 + + * c-decl.c (flexible_array_type_p): Move to common code. + 2019-11-30 Richard Sandiford <richard.sandiford@arm.com> * c-decl.c (start_decl): Allow initialization of variables whose diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index fa7dea5..bf1857d 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -5709,39 +5709,6 @@ check_compound_literal_type (location_t loc, struct c_type_name *type_name) "defining a type in a compound literal is invalid in C++"); } -/* Determine whether TYPE is a structure with a flexible array member, - or a union containing such a structure (possibly recursively). */ - -static bool -flexible_array_type_p (tree type) -{ - tree x; - switch (TREE_CODE (type)) - { - case RECORD_TYPE: - x = TYPE_FIELDS (type); - if (x == NULL_TREE) - return false; - while (DECL_CHAIN (x) != NULL_TREE) - x = DECL_CHAIN (x); - if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE - && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE - && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE - && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE) - return true; - return false; - case UNION_TYPE: - for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x)) - { - if (flexible_array_type_p (TREE_TYPE (x))) - return true; - } - return false; - default: - return false; - } -} - /* Performs sanity checks on the TYPE and WIDTH of the bit-field NAME, replacing with appropriate values if they are invalid. */ diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c index 4cea0f4..ca62226 100644 --- a/gcc/config/nios2/nios2.c +++ b/gcc/config/nios2/nios2.c @@ -2373,6 +2373,22 @@ nios2_in_small_data_p (const_tree exp) if (nios2_small_section_name_p (section)) return true; } + else if (flexible_array_type_p (TREE_TYPE (exp)) + && (!TREE_PUBLIC (exp) || DECL_EXTERNAL (exp))) + { + /* We really should not consider any objects of any flexibly-sized + type to be small data, but pre-GCC 10 did not test + for this and just fell through to the next case. Thus older + code compiled with -mgpopt=global could contain GP-relative + accesses to objects defined in this compilation unit with + external linkage. We retain the possible small-data treatment + of such definitions for backward ABI compatibility, but + no longer generate GP-relative accesses for external + references (so that the ABI could be changed in the future + with less potential impact), or objects with internal + linkage. */ + return false; + } else { HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp)); diff --git a/gcc/config/nios2/nios2.h b/gcc/config/nios2/nios2.h index 9dec57d..8867165 100644 --- a/gcc/config/nios2/nios2.h +++ b/gcc/config/nios2/nios2.h @@ -467,10 +467,10 @@ while (0) the linker seems to want the alignment of data objects to depend on their types. We do exactly that here. */ -#undef ASM_OUTPUT_ALIGNED_LOCAL -#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +#undef ASM_OUTPUT_ALIGNED_DECL_LOCAL +#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \ do { \ - if ((SIZE) <= nios2_section_threshold) \ + if (targetm.in_small_data_p (DECL)) \ switch_to_section (sbss_section); \ else \ switch_to_section (bss_section); \ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d499052..edf8ead 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2019-12-01 Sandra Loosemore <sandra@codesourcery.com> + + PR target/92499 + + * gcc.target/nios2/pr92499-1.c: New. + * gcc.target/nios2/pr92499-2.c: New. + * gcc.target/nios2/pr92499-3.c: New. + 2019-12-02 Luo Xiong Hu <luoxhu@linux.ibm.com> testsuite/pr92398 diff --git a/gcc/testsuite/gcc.target/nios2/pr92499-1.c b/gcc/testsuite/gcc.target/nios2/pr92499-1.c new file mode 100644 index 0000000..3985917 --- /dev/null +++ b/gcc/testsuite/gcc.target/nios2/pr92499-1.c @@ -0,0 +1,48 @@ +/* PR target/92499 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mgpopt=global -G8" } */ + +/* Check placement and addressing of flexibly-sized objects with internal + linkage. */ + +enum { size = 100 }; + +struct flexible +{ + int length; + int data[]; +}; + +static struct flexible local_flexible = + { + .data = { [size - 1] = 0, } + }; + +static struct flexible local_flexible_nonzero = + { + .length = size, + .data = { [size - 1] = 0, } + }; + +struct flexible * +get_local_flexible (void) +{ + return &local_flexible; +} + +struct flexible * +get_local_flexible_nonzero (void) +{ + return &local_flexible_nonzero; +} + +/* We should not place the flexibly-sized objects in small data + sections, or generate gp-relative addresses for them. */ + +/* { dg-final { scan-assembler-not "\\.sdata" } } */ +/* { dg-final { scan-assembler-not "\\.sbss" } } */ +/* { dg-final { scan-assembler-not "%gprel\(.*flexible.*\)" } } */ + + + + diff --git a/gcc/testsuite/gcc.target/nios2/pr92499-2.c b/gcc/testsuite/gcc.target/nios2/pr92499-2.c new file mode 100644 index 0000000..e253d0a --- /dev/null +++ b/gcc/testsuite/gcc.target/nios2/pr92499-2.c @@ -0,0 +1,45 @@ +/* PR target/92499 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mgpopt=global -G8" } */ + +/* Check placement and addressing of flexibly-sized objects with external + linkage. */ + +enum { size = 100 }; + +struct flexible +{ + int length; + int data[]; +}; + +extern struct flexible global_flexible; +struct flexible global_flexible = + { + .data = { [size - 1] = 0, } + }; + +extern struct flexible global_flexible_nonzero; +struct flexible global_flexible_nonzero = + { + .length = size, + .data = { [size - 1] = 0, } + }; + +struct flexible * +get_global_flexible (void) +{ + return &global_flexible; +} + +struct flexible * +get_global_flexible_nonzero (void) +{ + return &global_flexible_nonzero; +} + +/* To preserve ABI compatibility we place the flexibly-sized objects in + small data sections. */ + +/* { dg-final { scan-assembler-times "\\.sdata" 1 } } */ +/* { dg-final { scan-assembler-times "\\.sbss" 1 } } */ diff --git a/gcc/testsuite/gcc.target/nios2/pr92499-3.c b/gcc/testsuite/gcc.target/nios2/pr92499-3.c new file mode 100644 index 0000000..faeef05 --- /dev/null +++ b/gcc/testsuite/gcc.target/nios2/pr92499-3.c @@ -0,0 +1,23 @@ +/* PR target/92499 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mgpopt=global -G8" } */ + +/* Check addressing of extern flexibly-sized objects. */ + +struct flexible +{ + int length; + int data[]; +}; + +extern struct flexible extern_flexible; + +struct flexible * +get_extern_flexible (void) +{ + return &extern_flexible; +} + +/* We should not generate GP-relative addresses for external objects of + unknown size. */ +/* { dg-final { scan-assembler-not "%gprel\(.*flexible.*\)" } } */ @@ -15003,6 +15003,41 @@ default_is_empty_record (const_tree type) return default_is_empty_type (TYPE_MAIN_VARIANT (type)); } +/* Determine whether TYPE is a structure with a flexible array member, + or a union containing such a structure (possibly recursively). */ + +bool +flexible_array_type_p (const_tree type) +{ + tree x, last; + switch (TREE_CODE (type)) + { + case RECORD_TYPE: + last = NULL_TREE; + for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x)) + if (TREE_CODE (x) == FIELD_DECL) + last = x; + if (last == NULL_TREE) + return false; + if (TREE_CODE (TREE_TYPE (last)) == ARRAY_TYPE + && TYPE_SIZE (TREE_TYPE (last)) == NULL_TREE + && TYPE_DOMAIN (TREE_TYPE (last)) != NULL_TREE + && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (last))) == NULL_TREE) + return true; + return false; + case UNION_TYPE: + for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x)) + { + if (TREE_CODE (x) == FIELD_DECL + && flexible_array_type_p (TREE_TYPE (x))) + return true; + } + return false; + default: + return false; + } +} + /* Like int_size_in_bytes, but handle empty records specially. */ HOST_WIDE_INT @@ -6138,6 +6138,7 @@ extern void gt_pch_nx (tree &, gt_pointer_operator, void *); extern bool nonnull_arg_p (const_tree); extern bool default_is_empty_record (const_tree); +extern bool flexible_array_type_p (const_tree); extern HOST_WIDE_INT arg_int_size_in_bytes (const_tree); extern tree arg_size_in_bytes (const_tree); extern bool expr_type_first_operand_type_p (tree_code); |