aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJim Wilson <jimw@sifive.com>2019-08-08 19:04:56 +0000
committerJim Wilson <wilson@gcc.gnu.org>2019-08-08 12:04:56 -0700
commite98c3ee9712a360b4f470f930ac0c68863db1d3f (patch)
tree074a5f773ee577199037d614dad492689e2bd083 /gcc
parent355229f22a06073a288f6da189ea2757c5e09e30 (diff)
downloadgcc-e98c3ee9712a360b4f470f930ac0c68863db1d3f.zip
gcc-e98c3ee9712a360b4f470f930ac0c68863db1d3f.tar.gz
gcc-e98c3ee9712a360b4f470f930ac0c68863db1d3f.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/riscv/riscv.c92
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.target/riscv/flattened-struct-abi-1.c9
-rw-r--r--gcc/testsuite/gcc.target/riscv/flattened-struct-abi-2.c9
5 files changed, 113 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 54f7d97..9b939c1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index 431e90a..c12b26f 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -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;
+ }
+
+ /* 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;
+ }
- return n > 0 ? n : 0;
+ 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;
+
+ /* 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_old += SCALAR_FLOAT_TYPE_P (fields[i].type);
+ num_int_old += INTEGRAL_TYPE_P (fields[i].type);
+ }
+
+ /* 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);
+ }
- for (int i = 0; i < n; i++)
+ 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))
{
- num_float += SCALAR_FLOAT_TYPE_P (fields[i].type);
- num_int += INTEGRAL_TYPE_P (fields[i].type);
+ warning (0, "ABI for flattened struct with zero-length bit-fields "
+ "changed in GCC 10");
+ warned = 1;
}
- return num_int == 1 && num_float == 1;
+ return num_int_new == 1 && num_float_new == 1;
}
/* Return the representation of an argument passed or returned in an FPR
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c44e379..94b8852 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.target/riscv/flattened-struct-abi-1.c b/gcc/testsuite/gcc.target/riscv/flattened-struct-abi-1.c
new file mode 100644
index 0000000..f6a3c51
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/flattened-struct-abi-1.c
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/flattened-struct-abi-2.c b/gcc/testsuite/gcc.target/riscv/flattened-struct-abi-2.c
new file mode 100644
index 0000000..760826a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/flattened-struct-abi-2.c
@@ -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);
+}