On 2023/5/25 10:46, Lulu Cheng wrote:

在 2023/5/25 上午4:15, Jason Merrill 写道:
On Wed, May 24, 2023 at 5:00 AM Jonathan Wakely via Gcc-patches <gcc-patches@gcc.gnu.org <mailto:gcc-patches@gcc.gnu.org>> wrote:

    On Wed, 24 May 2023 at 09:41, Xi Ruoyao <xry...@xry111.site> wrote:

    > Wang Lei raised some concerns about Itanium C++ ABI, so let's
    ask a C++
    > expert here...
    >
    > Jonathan: AFAIK the standard and the Itanium ABI treats an empty
    class
    > as size 1

    Only as a complete object, not as a subobject.


Also as a data member subobject.

    > in order to guarantee unique address, so for the following:
    >
    > class Empty {};
    > class Test { Empty empty; double a, b; };

    There is no need to have a unique address here, so Test::empty and
    Test::a
    have the same address. It's a potentially-overlapping subobject.

    For the Itanium ABI, sizeof(Test) == 2 * sizeof(double).


That would be true if Test::empty were marked [[no_unique_address]], but without that attribute, sizeof(Test) is actually 3 * sizeof(double).

    > When we pass "Test" via registers, we may only allocate the
    registers
    > for Test::a and Test::b, and complete ignore Test::empty because
    there
    > is no addresses of registers.  Is this correct or not?

    I think that's a decision for the loongarch psABI. In principle,
    there's no
    reason a register has to be used to pass Test::empty, since you
    can't read
    from it or write to it.


Agreed.  The Itanium C++ ABI has nothing to say about how registers are allocated for parameter passing; this is a matter for the psABI.

And there is no need for a psABI to allocate a register for Test::empty because it contains no data.

In the x86_64 psABI, Test above is passed in memory because of its size ("the size of the aggregate exceeds two eightbytes...").  But

struct Test2 { Empty empty; double a; };

is passed in a single floating-point register; the Test2::empty subobject is not passed anywhere, because its eightbyte is classified as NO_CLASS, because there is no actual data there.




I know nothing about the LoongArch psABI, but going out of your way to assign a register to an empty class seems like a mistake.

MIPS64 and ARM64 also allocate parameter registers for empty structs. https://godbolt.org/z/jT4cY3T5o

Our original intention is not to pass this empty structure member, but to make the following two structures treat empty structure members

in the same way in the process of passing parameters.

struct st1
{
     struct empty {} e1;
     long a;
     long b;
};

struct st2
{
     struct empty {} e1;
     double f0;
     double f1;
};

Then shouldn't we try to avoid the extra register in all cases, instead of wasting one regardless? ;-)

Reply via email to