RISC-V: Fix C ABI for flattened struct with 0-length bitfield.
gcc/ PR target/91229 * config/riscv/riscv.c (riscv_flatten_aggregate_field): New arg ignore_zero_width_bit_field_p. Skip zero size bitfields when true. Pass into recursive call. (riscv_flatten_aggregate_argument): New arg. Pass to riscv_flatten_aggregate_field. (riscv_pass_aggregate_in_fpr_pair_p): New local warned. Call riscv_flatten_aggregate_argument twice, with false and true as last arg. Process result twice. Compare results and warn if different. (riscv_pass_aggregate_in_fpr_and_gpr_p): Likewise. gcc/testsuite/ * gcc.target/riscv/flattened-struct-abi-1.c: New test. * gcc.target/riscv/flattened-struct-abi-2.c: New test. From-SVN: r274215
This commit is contained in:
parent
355229f22a
commit
e98c3ee971
5 changed files with 113 additions and 16 deletions
|
@ -1,3 +1,16 @@
|
|||
2019-08-08 Jim Wilson <jimw@sifive.com>
|
||||
|
||||
PR target/91229
|
||||
* config/riscv/riscv.c (riscv_flatten_aggregate_field): New arg
|
||||
ignore_zero_width_bit_field_p. Skip zero size bitfields when true.
|
||||
Pass into recursive call.
|
||||
(riscv_flatten_aggregate_argument): New arg. Pass to
|
||||
riscv_flatten_aggregate_field.
|
||||
(riscv_pass_aggregate_in_fpr_pair_p): New local warned. Call
|
||||
riscv_flatten_aggregate_argument twice, with false and true as last
|
||||
arg. Process result twice. Compare results and warn if different.
|
||||
(riscv_pass_aggregate_in_fpr_and_gpr_p): Likewise.
|
||||
|
||||
2019-08-08 Martin Liska <mliska@suse.cz>
|
||||
|
||||
PR bootstrap/91352
|
||||
|
|
|
@ -2383,7 +2383,8 @@ typedef struct {
|
|||
static int
|
||||
riscv_flatten_aggregate_field (const_tree type,
|
||||
riscv_aggregate_field fields[2],
|
||||
int n, HOST_WIDE_INT offset)
|
||||
int n, HOST_WIDE_INT offset,
|
||||
bool ignore_zero_width_bit_field_p)
|
||||
{
|
||||
switch (TREE_CODE (type))
|
||||
{
|
||||
|
@ -2400,8 +2401,21 @@ riscv_flatten_aggregate_field (const_tree type,
|
|||
if (!TYPE_P (TREE_TYPE (f)))
|
||||
return -1;
|
||||
|
||||
HOST_WIDE_INT pos = offset + int_byte_position (f);
|
||||
n = riscv_flatten_aggregate_field (TREE_TYPE (f), fields, n, pos);
|
||||
/* The C++ front end strips zero-length bit-fields from structs.
|
||||
So we need to ignore them in the C front end to make C code
|
||||
compatible with C++ code. */
|
||||
if (ignore_zero_width_bit_field_p
|
||||
&& DECL_BIT_FIELD (f)
|
||||
&& (DECL_SIZE (f) == NULL_TREE
|
||||
|| integer_zerop (DECL_SIZE (f))))
|
||||
;
|
||||
else
|
||||
{
|
||||
HOST_WIDE_INT pos = offset + int_byte_position (f);
|
||||
n = riscv_flatten_aggregate_field (TREE_TYPE (f),
|
||||
fields, n, pos,
|
||||
ignore_zero_width_bit_field_p);
|
||||
}
|
||||
if (n < 0)
|
||||
return -1;
|
||||
}
|
||||
|
@ -2414,7 +2428,8 @@ riscv_flatten_aggregate_field (const_tree type,
|
|||
tree index = TYPE_DOMAIN (type);
|
||||
tree elt_size = TYPE_SIZE_UNIT (TREE_TYPE (type));
|
||||
int n_subfields = riscv_flatten_aggregate_field (TREE_TYPE (type),
|
||||
subfields, 0, offset);
|
||||
subfields, 0, offset,
|
||||
ignore_zero_width_bit_field_p);
|
||||
|
||||
/* Can't handle incomplete types nor sizes that are not fixed. */
|
||||
if (n_subfields <= 0
|
||||
|
@ -2487,12 +2502,14 @@ riscv_flatten_aggregate_field (const_tree type,
|
|||
|
||||
static int
|
||||
riscv_flatten_aggregate_argument (const_tree type,
|
||||
riscv_aggregate_field fields[2])
|
||||
riscv_aggregate_field fields[2],
|
||||
bool ignore_zero_width_bit_field_p)
|
||||
{
|
||||
if (!type || TREE_CODE (type) != RECORD_TYPE)
|
||||
return -1;
|
||||
|
||||
return riscv_flatten_aggregate_field (type, fields, 0, 0);
|
||||
return riscv_flatten_aggregate_field (type, fields, 0, 0,
|
||||
ignore_zero_width_bit_field_p);
|
||||
}
|
||||
|
||||
/* See whether TYPE is a record whose fields should be returned in one or
|
||||
|
@ -2502,13 +2519,34 @@ static unsigned
|
|||
riscv_pass_aggregate_in_fpr_pair_p (const_tree type,
|
||||
riscv_aggregate_field fields[2])
|
||||
{
|
||||
int n = riscv_flatten_aggregate_argument (type, fields);
|
||||
static int warned = 0;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
/* This is the old ABI, which differs for C++ and C. */
|
||||
int n_old = riscv_flatten_aggregate_argument (type, fields, false);
|
||||
for (int i = 0; i < n_old; i++)
|
||||
if (!SCALAR_FLOAT_TYPE_P (fields[i].type))
|
||||
return 0;
|
||||
{
|
||||
n_old = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return n > 0 ? n : 0;
|
||||
/* This is the new ABI, which is the same for C++ and C. */
|
||||
int n_new = riscv_flatten_aggregate_argument (type, fields, true);
|
||||
for (int i = 0; i < n_new; i++)
|
||||
if (!SCALAR_FLOAT_TYPE_P (fields[i].type))
|
||||
{
|
||||
n_new = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((n_old != n_new) && (warned == 0))
|
||||
{
|
||||
warning (0, "ABI for flattened struct with zero-length bit-fields "
|
||||
"changed in GCC 10");
|
||||
warned = 1;
|
||||
}
|
||||
|
||||
return n_new > 0 ? n_new : 0;
|
||||
}
|
||||
|
||||
/* See whether TYPE is a record whose fields should be returned in one or
|
||||
|
@ -2519,16 +2557,38 @@ static bool
|
|||
riscv_pass_aggregate_in_fpr_and_gpr_p (const_tree type,
|
||||
riscv_aggregate_field fields[2])
|
||||
{
|
||||
unsigned num_int = 0, num_float = 0;
|
||||
int n = riscv_flatten_aggregate_argument (type, fields);
|
||||
static int warned = 0;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
/* This is the old ABI, which differs for C++ and C. */
|
||||
unsigned num_int_old = 0, num_float_old = 0;
|
||||
int n_old = riscv_flatten_aggregate_argument (type, fields, false);
|
||||
for (int i = 0; i < n_old; i++)
|
||||
{
|
||||
num_float += SCALAR_FLOAT_TYPE_P (fields[i].type);
|
||||
num_int += INTEGRAL_TYPE_P (fields[i].type);
|
||||
num_float_old += SCALAR_FLOAT_TYPE_P (fields[i].type);
|
||||
num_int_old += INTEGRAL_TYPE_P (fields[i].type);
|
||||
}
|
||||
|
||||
return num_int == 1 && num_float == 1;
|
||||
/* This is the new ABI, which is the same for C++ and C. */
|
||||
unsigned num_int_new = 0, num_float_new = 0;
|
||||
int n_new = riscv_flatten_aggregate_argument (type, fields, true);
|
||||
for (int i = 0; i < n_new; i++)
|
||||
{
|
||||
num_float_new += SCALAR_FLOAT_TYPE_P (fields[i].type);
|
||||
num_int_new += INTEGRAL_TYPE_P (fields[i].type);
|
||||
}
|
||||
|
||||
if (((num_int_old == 1 && num_float_old == 1
|
||||
&& (num_int_old != num_int_new || num_float_old != num_float_new))
|
||||
|| (num_int_new == 1 && num_float_new == 1
|
||||
&& (num_int_old != num_int_new || num_float_old != num_float_new)))
|
||||
&& (warned == 0))
|
||||
{
|
||||
warning (0, "ABI for flattened struct with zero-length bit-fields "
|
||||
"changed in GCC 10");
|
||||
warned = 1;
|
||||
}
|
||||
|
||||
return num_int_new == 1 && num_float_new == 1;
|
||||
}
|
||||
|
||||
/* Return the representation of an argument passed or returned in an FPR
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2019-08-08 Jim Wilson <jimw@sifive.com>
|
||||
|
||||
PR target/91229
|
||||
* gcc.target/riscv/flattened-struct-abi-1.c: New test.
|
||||
* gcc.target/riscv/flattened-struct-abi-2.c: New test.
|
||||
|
||||
2019-08-08 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c++/79520
|
||||
|
|
9
gcc/testsuite/gcc.target/riscv/flattened-struct-abi-1.c
Normal file
9
gcc/testsuite/gcc.target/riscv/flattened-struct-abi-1.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-march=rv32gc -mabi=ilp32d" } */
|
||||
struct s1 { int : 0; float f; int i; int : 0; };
|
||||
|
||||
void dummy(float, int);
|
||||
|
||||
void f(struct s1 s) { /* { dg-warning "flattened struct" } */
|
||||
dummy(s.f + 1.0, s.i + 1);
|
||||
}
|
9
gcc/testsuite/gcc.target/riscv/flattened-struct-abi-2.c
Normal file
9
gcc/testsuite/gcc.target/riscv/flattened-struct-abi-2.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-march=rv32gc -mabi=ilp32d" } */
|
||||
struct s1 { int : 0; float f; float g; int : 0; };
|
||||
|
||||
void dummy(float, float);
|
||||
|
||||
void f(struct s1 s) { /* { dg-warning "flattened struct" } */
|
||||
dummy(s.f + 1.0, s.g + 2.0);
|
||||
}
|
Loading…
Add table
Reference in a new issue