+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
+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
"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. */
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));
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); \
+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
--- /dev/null
+/* 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.*\)" } } */
+
+
+
+
--- /dev/null
+/* 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 } } */
--- /dev/null
+/* 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.*\)" } } */
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
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);