gcc/riscv: Correctly ignore empty C++ structs when flattening for ABI
authorAndrew Burgess <andrew.burgess@embecosm.com>
Mon, 18 Mar 2019 10:42:53 +0000 (10:42 +0000)
committerAndrew Burgess <aburgess@gcc.gnu.org>
Mon, 18 Mar 2019 10:42:53 +0000 (10:42 +0000)
commit4d7dfada8935a362601d1782bd6598e3e1d78d74
treeefcd19f09fda1f82385ba0d28684f52175df14b8
parente6da0bf1f15cdb0d641b77af75b7cb511ef9b553
gcc/riscv: Correctly ignore empty C++ structs when flattening for ABI

This fixes PR target/89627.

The RISC-V ABI document[1] says:

   For the purposes of this section, "struct" refers to a C struct
   with its hierarchy flattened, including any array fields. That is,
   struct { struct { float f[1]; } g[2]; } and struct { float f; float
   g; } are treated the same. Fields containing empty structs or
   unions are ignored while flattening, even in C++, unless they have
   nontrivial copy constructors or destructors.

However, this flattening only applies when one of the fields of the
flattened structure can be placed into a floating point register,
otherwise no flattening occurs.

Currently GCC fails to correctly consider that empty C++ structures
have a non-zero size when constructing the arguments from a flattened
structure, and as a result, trying to pass a C++ structure like this:

  struct sf { struct {} e; float f; };

Doesn't work correctly, GCC fails to take the offset of 'f' within
'sf' into account and will actually pass the space backing 'e' as the
contents of 'f'.

This patch fixes this so that 'f' will be passed correctly.  A couple
of new tests are added to cover this functionality.

[1] https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md

gcc/ChangeLog:

PR target/89627
* config/riscv/riscv.c (riscv_pass_fpr_single): Add offset
parameter, and make use of it.
(riscv_get_arg_info): Pass offset to riscv_pass_fpr_single.

gcc/testsuite/ChangeLog:

PR target/89627
* g++.target/riscv/call-with-empty-struct-float.C: New file.
* g++.target/riscv/call-with-empty-struct-int.C: New file.
* g++.target/riscv/call-with-empty-struct.H: New file.
* g++.target/riscv/riscv.exp: New file.

From-SVN: r269760
gcc/ChangeLog
gcc/config/riscv/riscv.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.target/riscv/call-with-empty-struct-float.C [new file with mode: 0644]
gcc/testsuite/g++.target/riscv/call-with-empty-struct-int.C [new file with mode: 0644]
gcc/testsuite/g++.target/riscv/call-with-empty-struct.H [new file with mode: 0644]
gcc/testsuite/g++.target/riscv/riscv.exp [new file with mode: 0644]