C++ Logo


Advanced search

Re: [std-proposals] Custom call convention per type

From: Avi Kivity <avi_at_[hidden]>
Date: Sun, 7 Aug 2022 22:05:06 +0300
On 07/08/2022 21.31, Jason McKesson via Std-Proposals wrote:
> On Sun, Aug 7, 2022 at 10:21 AM Avi Kivity via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
>> On 29/07/2022 21.42, Arthur O'Dwyer via Std-Proposals wrote:
>> On Fri, Jul 29, 2022 at 2:26 PM Marcin Jaczewski <marcinjaczewski86_at_[hidden]> wrote:
>>> pt., 29 lip 2022 o 20:20 Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]> napisaƂ(a):
>>>> On Thu, Jul 28, 2022 at 5:26 PM Marcin Jaczewski via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>>>> Currently there are multiple problems linked to lifetime of function parameters.
>>>>> Simply current default behavior does not fit all corner cases.
>>>>> Example is `std::unique` that generates subpar code because the call
>>>>> site is a firewall that prevents the compiler to see at once destructor and move operation.
>>>> Can you elaborate on this? I admit I've never thought about `std::unique` in this context before; but now that I have spent an hour or so thinking about it, I still don't see how its current behavior can be improved. One might rewrite `std::unique` to use swap instead of move-assignment, but one can't really rewrite it to use relocation because `std::unique` is never responsible for destroying anything. N objects go in, N objects come out (and in the same memory locations, too).
>>>> https://p1144.godbolt.org/z/8v1Yj1eGK
>>>> What would you do differently here?
>>> Sorry, I mistyped, I mean type `std::unique_ptr` not algorythm `std::unique`.
>> Aha. In that case, is your proposal any different from the existing attribute [[trivial_abi]]?
>> https://quuxplusone.github.io/blog/2018/05/02/trivial-abi-101/
>> https://libcxx.llvm.org//DesignDocs/UniquePtrTrivialAbi.html
>> https://godbolt.org/z/f59T4Tev1
>> ([[trivial_abi]] is vendor-specific, not part of the ISO standard; but if your proposal really just boils down to "Hey, WG21 should just standardize [[trivial_abi]]," then you should say that.)
>> IMO, that's wrong. The standard leaves the ABI to the implementation. Standardizing [[trivial_abi]] means the standard acknowledges multiple ABIs, and requires the user to micro-manage the ABI of each type if they care about performance.
>> The implementations should just switch to a better ABI - callee-destroy, and pass-by-register if it can prove no self-references are involved (e.g. by type-based alias analysis, trivial for std::unique_ptr).
>> Yes, switching ABIs is a huge pain, but it has been managed in the past. gcc switched from reference-counted std::string to non-reference-counted std::string with SBO, and there were minor ABI updates when bugs were found in the implementation. The implementations are stuck in a deep hole, but [[trivial_abi]] makes that hole a little deeper.
> It's important to understand the sheer *magnitude* of the ABI change
> you're talking about compared to that of `std::string` in C++11.
> The `std::string` change only affected your code if you used
> `std::string` to communicate with code outside of your static
> compilation/linking. And the thing is... there actually wasn't all
> *that* much such code. That's not to say that there was none, but it
> wasn't a huge amount. There are entire libraries that don't deal in
> strings at their interface sites, or just don't use `std::string`
> directly in interfaces.
> Indeed, not using standard library types in interfaces is quite
> common, specifically to avoid such ABI problems.
> By contrast, the kind of ABI change you're talking about would
> effectively break *every function* that happens to use *any* by-value
> parameter of a user-defined type. That's a *lot* more code.

I absolutely agree that it's a larger problem. But std::string is the
most common of library types. Any large program will use it, and will
communicate with libraries as well.

> Now, I don't much care for "trivial ABI" as a feature. But the idea
> that it would *ever* be at all practical to change every ABI on every
> platform in such a way is absurd. No matter how much nicer it might
> be, it is not going to happen. So we can either continue to see the
> problem go unsolved or try to find actual functional solutions.

I don't think it's so far fetched. The compilers will just implement
both ABIs (they already support multiple ABIs, since most target both
Windows and Linux).

The fast-moving distributions (Fedora etc.) will just switch to the new
ABI and ask their users to recompile.

The slow-moving distributions (RHEL and its clones) will pick one ABI
and stick with it for the lifetime of the distribution. That's 10
years+, during which third-party vendors have time to recompile for the
new ABI. Typically they'll have to anyway, since so much changes between
major releases.

The advantage of a Standard change is that it effectively forces the
compiler vendors to fix the problem, but the quality of the fix is much
lower since it has to be manually managed. It also introduces new
interoperability problems, since a compiler that doesn't recognize the
attribute will not interoperate with a compiler that does, if the
attribute is used.

Received on 2022-08-07 19:05:10