How about some __initialize magic?
Stanislav Blinov
stanislav.blinov at gmail.com
Sun Nov 28 08:30:18 UTC 2021
On Sunday, 28 November 2021 at 02:15:37 UTC, kinke wrote:
> On Saturday, 27 November 2021 at 21:56:05 UTC, Stanislav Blinov
> wrote:
>> [...]
>> Upcoming `__traits(initSymbol)` would help in removing the
>> hack,
>
> It's already removed in master.
Cool!
>> but won't help CTFE any. At various points of their lives,
>> these things even explicitly called `memcpy`, which is just...
>> argh! And some still do (`copyEmplace`, I'm looking at you).
>> Call into CRT to blit a 8-byte struct? With statically known
>> size and alignment? Just to sidestep type system? Eh???
>
> 1. Most optimizers recognize a memcmp call and its semantics,
> and try to avoid the lib call accordingly.
I'd rather not leave this to "try". Not only because it's work
that needn't be done, but also for debug performance. Exactly the
stuff you talk about at the end of your post :D
> 2. A slice copy (`source[] = target[]` with e.g. void[]-typed
> slices) is a memcpy with additional potential checks for
> matching length and no overlap (with enabled bounds checks
> IIRC), so memcpy avoids that overhead. It also works with
> -betterC; e.g., the aforementioned checks are implemented as a
> druntime helper function for LDC and so not available with
> -betterC.
Slice copies aren't needed :) Nor would they work in CTFE, as
that requires reinterpret-casting a T to a slice.
> 3. I haven't checked, but if memcpy is the only real CTFE
> blocker for emplace at the moment, I guess one option would be
> extending the CTFE interpreter by a memcpy builtin, in order
> not to have to further uglify the existing library code.
`emplace` is also deficient:
https://github.com/dlang/druntime/blob/2b7873da09c63761fe6e69dc4dd225c0844ed4e9/src/core/internal/lifetime.d#L31-L59
Also note that that's already one call down from `emplace`, and
potentially could `move` the bits or copy the argument(s) again
(to call the fake struct ctor), and then, of course, again, in
implementation of that fake ctor. Same goes for the actual
non-fake struct `__ctor` version. Initializing large structs or
those having expensive copy ctors is no fun. `-O` build may help
with some of that, of course, but again I'd rather this didn't
need to be in the first place.
`emplaceInitializer` also may not work in all cases. Current one
would fail on that mangling business, upcoming one - because
`__traits(initSymbol)` gives you a `void[]`, meaning a
reinterpret cast is needed somewhere, meaning no dice for CTFE.
And that means none of these guys would work when initializer is
required, since everyone in the `emplace` family is dependent on
`emplaceInitializer`. So CTFE-able implementation would be back
to union fun. Except, of course, for classes, which is...
questionable.
Making `mem*` functions available to CTFE would be a big
improvement for sure, but it only solves half the problem (the
other being reinterpret casts).
`emplace` in CTFE should fail for one reason only - if the ctor
is not CTFE-able (i.e. that's caller's responsibility). So far,
it may fail for reasons that are down to language plumbing :(
>> What do you think? DIP this, yay or nay? Suggestions?..
>
> I'm not convinced I'm afraid. :) - I've been thinking in the
> other direction, treating core.lifetime.{move,forward} as
> builtins for codegen (possibly restricted to function call
> argument expressions), in order to save work for the optimizer
> and less bloat for debug builds.
A compiler extension? Wouldn't that require semantics to be the
same? Surely you wouldn't want to artificially limit their
implementation in compiler just because library versions are
deficient?
I mean, I'm not against this idea, but AFAIUI that route mandates
we make library versions more robust. Then again, why have four
builtins where one can suffice? ;)
More information about the Digitalmars-d
mailing list