C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Relocation in C++

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Mon, 19 Dec 2022 12:55:00 -0500
On Mon, Dec 19, 2022 at 12:05 PM Edward Catmur via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On Mon, 19 Dec 2022 at 17:52, Giuseppe D'Angelo via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>>
>> I'm not really sure without reading something concrete, but this seems
>> to be falling the same bucket of synthesizing copies / moves /
>> relocations (P1144) (/ [[trivial_abi]]), i.e. things compose
>> "automatically" by default or you've got type traits to allow you to
>> choose a composition strategy.
>>
>
> Yes, I agree on that part, if you mean that they should compose
> automatically for defaulted special member functions (including for
> aggregates).
>

The most recent syntax
optional(optional) [[no_parameter_reloc(is_no_parameter_reloc<T>)]];
variant(variant) [[no_parameter_reloc(is_no_parameter_reloc<Types> or
...)]];
certainly seems to be gravitating toward the P1144 propagation solution, as
seen in my libc++ fork here for example:

https://github.com/llvm/llvm-project/commit/cc0addf5ab7f84a1a959addc2d69f6ac38d07e98#diff-bbea28f47b73848b21aca02ff43cea0dd32a070825ce786de3d9566bd7ed4717

https://github.com/llvm/llvm-project/commit/cc0addf5ab7f84a1a959addc2d69f6ac38d07e98#diff-2c05a5b3a75a81a99615776824dcdc7e612b081e88f024d389e83e834eb20f1e

The difference I see between this and P1144 is that this is conflating
trivial_abi with trivial relocatability (even though there are types which
are trivially relocatable that we probably don't want to be trivial_abi,
such as `std::array<int, 1000>`) and even with non-trivial relocatability.
It's almost like a "customizable trivial_abi" at this point — "take this
type and pass it by trivial_abi, except that each time the object teleports
from one memory address through a register to another memory address, run
*this* code."
And the problem I see with that is that the "teleport" operation is really
*two* operations: "slurp from memory into a register" on the caller's side,
and "blat from register back into memory" on the callee's side. For types
that are trivially relocatable, both operations are trivial. For types
that aren't trivially relocatable, it's unclear what these two operations
should actually do, and in particular whether the in-register
representation can be used directly at all. And collapsing them both into
`T(T)` (however it's ultimately spelled) feels like a problem.

Have you tried "manually implementing" this idea, by showing some simple
examples of `T(T)` and then showing the machine code generated from them?
Assume that nothing is inlined or optimized — so you're not allowed to
"cheat" by eliding any operations — just show exactly how the `T(T)`
constructor would be codegenned, and then what a call to it would look
like, and so on.

HTH,
Arthur

Received on 2022-12-19 17:55:14