Fix bugs relating to flexibly-sized objects in nios2 backend.
authorSandra Loosemore <sandra@codesourcery.com>
Mon, 2 Dec 2019 03:52:15 +0000 (22:52 -0500)
committerSandra Loosemore <sandra@gcc.gnu.org>
Mon, 2 Dec 2019 03:52:15 +0000 (22:52 -0500)
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

gcc/ChangeLog
gcc/c/ChangeLog
gcc/c/c-decl.c
gcc/config/nios2/nios2.c
gcc/config/nios2/nios2.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/nios2/pr92499-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/nios2/pr92499-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/nios2/pr92499-3.c [new file with mode: 0644]
gcc/tree.c
gcc/tree.h

index 0b012af497af36da8c2bf588df943eb99e289207..9a807baa38e8e31c8198c1609fb008a898c0d4a0 100644 (file)
@@ -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
index 8fee474346f1bd20c61dd7a9b36bfc90bd5c2662..c04443ea6f9f9178f8813e1591834dd8592a9b08 100644 (file)
@@ -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
index fa7dea5afb5f8d24a4fff3cb10c6a7909eb4349c..bf1857dc3fae63bf5ef845018d740c26e23214dc 100644 (file)
@@ -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++");
 }
 \f
-/* 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;
-  }
-}
-\f
 /* Performs sanity checks on the TYPE and WIDTH of the bit-field NAME,
    replacing with appropriate values if they are invalid.  */
 
index 4cea0f4e2f2e91e024e0b197ba17ab823908e200..ca6222658a956e841767265c694673fecbc37140 100644 (file)
@@ -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));
index 9dec57d67aecd1d699e0f6f4a88f94d7c475a30b..886716527073cb943c13ba21848e9ff6a384e449 100644 (file)
@@ -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);                                   \
index d49905272446c708e7ee32d60cc71d4319015b45..edf8eadae037175157bf84c9f2d70ba0a30d6e58 100644 (file)
@@ -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 (file)
index 0000000..3985917
--- /dev/null
@@ -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 (file)
index 0000000..e253d0a
--- /dev/null
@@ -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 (file)
index 0000000..faeef05
--- /dev/null
@@ -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.*\)" } } */
index 1bb37679f5429718eb550781b7f56957f6a84b22..7a66d1003ee2887d938eaa0483916333f8ce237a 100644 (file)
@@ -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
index 0f3cc5d7e5a380cfdcff178a94abbe87cb822324..fb09758a05af83232bfc58cb032029d1d31928a1 100644 (file)
@@ -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);