Commit 4569f8b3 by Sandra Loosemore Committed by Sandra Loosemore

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
parent e549dd44
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> 2019-11-30 Jan Hubicka <hubicka@ucw.cz>
* profile-count.h (profile_count::operator<): Use IPA value for * 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> 2019-11-30 Richard Sandiford <richard.sandiford@arm.com>
* c-decl.c (start_decl): Allow initialization of variables whose * c-decl.c (start_decl): Allow initialization of variables whose
......
...@@ -5709,39 +5709,6 @@ check_compound_literal_type (location_t loc, struct c_type_name *type_name) ...@@ -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++"); "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, /* Performs sanity checks on the TYPE and WIDTH of the bit-field NAME,
replacing with appropriate values if they are invalid. */ replacing with appropriate values if they are invalid. */
......
...@@ -2373,6 +2373,22 @@ nios2_in_small_data_p (const_tree exp) ...@@ -2373,6 +2373,22 @@ nios2_in_small_data_p (const_tree exp)
if (nios2_small_section_name_p (section)) if (nios2_small_section_name_p (section))
return true; 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 else
{ {
HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp)); HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
......
...@@ -467,10 +467,10 @@ while (0) ...@@ -467,10 +467,10 @@ while (0)
the linker seems to want the alignment of data objects the linker seems to want the alignment of data objects
to depend on their types. We do exactly that here. */ to depend on their types. We do exactly that here. */
#undef ASM_OUTPUT_ALIGNED_LOCAL #undef ASM_OUTPUT_ALIGNED_DECL_LOCAL
#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ #define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
do { \ do { \
if ((SIZE) <= nios2_section_threshold) \ if (targetm.in_small_data_p (DECL)) \
switch_to_section (sbss_section); \ switch_to_section (sbss_section); \
else \ else \
switch_to_section (bss_section); \ 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> 2019-12-02 Luo Xiong Hu <luoxhu@linux.ibm.com>
testsuite/pr92398 testsuite/pr92398
......
/* 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.*\)" } } */
/* 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 } } */
/* 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) ...@@ -15003,6 +15003,41 @@ default_is_empty_record (const_tree type)
return default_is_empty_type (TYPE_MAIN_VARIANT (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. */ /* Like int_size_in_bytes, but handle empty records specially. */
HOST_WIDE_INT HOST_WIDE_INT
......
...@@ -6138,6 +6138,7 @@ extern void gt_pch_nx (tree &, gt_pointer_operator, void *); ...@@ -6138,6 +6138,7 @@ extern void gt_pch_nx (tree &, gt_pointer_operator, void *);
extern bool nonnull_arg_p (const_tree); extern bool nonnull_arg_p (const_tree);
extern bool default_is_empty_record (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 HOST_WIDE_INT arg_int_size_in_bytes (const_tree);
extern tree arg_size_in_bytes (const_tree); extern tree arg_size_in_bytes (const_tree);
extern bool expr_type_first_operand_type_p (tree_code); extern bool expr_type_first_operand_type_p (tree_code);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment