Thread overview
[Issue 20752] __traits(isReturnOnStack, func) is incomplete and can't be trusted
Apr 21, 2020
Iain Buclaw
Apr 21, 2020
kinke
Oct 05, 2020
Walter Bright
Dec 17, 2022
Iain Buclaw
April 21, 2020
https://issues.dlang.org/show_bug.cgi?id=20752

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ibuclaw@gdcproject.org

--- Comment #1 from Iain Buclaw <ibuclaw@gdcproject.org> ---
(In reply to Mathias LANG from comment #0)
> Since half of the logic for NRVO is in the backend, this traits simply cannot be relied on and is mostly useless.

For finding out if a struct is to be returned using (N)RVO, the right test to
use would be __traits(isPOD).

If a struct is non-POD, then it should _always_ be passed around by invisible reference, no ifs, no buts, no excuses.

However, that's ignoring static arrays, which is a little more hairy to find out, as they need to be big enough to be considered returning in memory.  But just what is "big enough" is a very target-specific question.


> For example, the following compiles and triggers the assert with DMD:
>
[--snip--]
> 
> I would expect a compilation error, or the assert to pass.

Worse, some back-ends can't provide any useful information as there's no access to "target".  This is from the gdc-ddmd branch with included explanation.

---
bool
Target::isReturnOnStack (TypeFunction *, bool)
{
  /* Need the back-end type to determine this, but this is called from the
     frontend before semantic processing is finished.  An accurate value
     is not currently needed anyway.  */
  return true;
}
---

A type could be synthesized, however. But it would be a best guess approach.

--
April 21, 2020
https://issues.dlang.org/show_bug.cgi?id=20752

kinke <kinke@gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |kinke@gmx.net

--- Comment #2 from kinke <kinke@gmx.net> ---
(In reply to Iain Buclaw from comment #1)
> For finding out if a struct is to be returned using (N)RVO, the right test
> to use would be __traits(isPOD).
> 
> If a struct is non-POD, then it should _always_ be passed around by invisible reference, no ifs, no buts, no excuses.
> 
> However, that's ignoring static arrays, which is a little more hairy to find out, as they need to be big enough to be considered returning in memory. But just what is "big enough" is a very target-specific question.

That goes for large structs too, not just static arrays, so isPOD is definitely not sufficient.

The isReturnOnStack trait isn't directly related to NRVO and only depends on the ABI; in LLVM lingo, passing a pointer to the pre-allocated result is called sret, struct-return. NRVO just means that a named variable in the callee will be emplaced into that memory directly, so an sret ABI requirement for the callee is an orthogonal prerequisite for NRVO to work (in the callee).

--
October 05, 2020
https://issues.dlang.org/show_bug.cgi?id=20752

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla@digitalmars.com

--- Comment #3 from Walter Bright <bugzilla@digitalmars.com> ---
> the following compiles and triggers the assert with DMD:

A much smaller example would be nice. For example, all those templates seem an unnecessary complication.

--
December 17, 2022
https://issues.dlang.org/show_bug.cgi?id=20752

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P1                          |P2

--