aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSandra Loosemore <sandra@codesourcery.com>2019-12-02 03:52:15 +0000
committerSandra Loosemore <sandra@codesourcery.com>2019-12-02 03:52:15 +0000
commita5fc5d9e9ee48138d09a357cc3b34c144e8616d4 (patch)
treef22f9ae555d8f38b980718893ef0bc8f71976ea5
parent26921dc8094c4d4fce83aa4260f30fcb7970bb32 (diff)
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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@278891 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/c/ChangeLog6
-rw-r--r--gcc/c/c-decl.c33
-rw-r--r--gcc/config/nios2/nios2.c16
-rw-r--r--gcc/config/nios2/nios2.h6
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gcc.target/nios2/pr92499-1.c48
-rw-r--r--gcc/testsuite/gcc.target/nios2/pr92499-2.c45
-rw-r--r--gcc/testsuite/gcc.target/nios2/pr92499-3.c23
-rw-r--r--gcc/tree.c35
-rw-r--r--gcc/tree.h1
11 files changed, 199 insertions, 36 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0b012af497a..9a807baa38e 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 8fee474346f..c04443ea6f9 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 fa7dea5afb5..bf1857dc3fa 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 4cea0f4e2f2..ca6222658a9 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 9dec57d67ae..88671652707 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 d4990527244..edf8eadae03 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 00000000000..3985917a10c
--- /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 00000000000..e253d0a056a
--- /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 00000000000..faeef050acf
--- /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.*\)" } } */
diff --git a/gcc/tree.c b/gcc/tree.c
index 1bb37679f54..7a66d1003ee 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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
diff --git a/gcc/tree.h b/gcc/tree.h
index 0f3cc5d7e5a..fb09758a05a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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);