-preview=in might break code
kinke
noone at nowhere.com
Mon Oct 5 13:27:00 UTC 2020
On Monday, 5 October 2020 at 07:56:00 UTC, Iain Buclaw wrote:
> Correct me if I'm wrong, but it looks like we'll have three
> competing implementations:
>
> DMD: `const scope`, with `ref` applied on types usually passed
> in memory.
> LDC: `const scope ref @restrict`
> GDC: `const scope` with `ref` applied on types usually passed
> by invisible reference.
Non-PODs are always by-ref, so wrt. PODs only:
DMD: Currently (2.094) `ref` for all types > 2 machine words,
with a little exception for x87 `real` on Win64 (ref). To be
improved.
LDC: With https://github.com/ldc-developers/ldc/pull/3578, `ref`
for all types which would be passed by invisible ref (Win64,
AArch64), or passed on the stack and larger than 2 machine words
(Posix x86_64, 32-bit x86). For all other ABIs (I'm not really
familiar with): `ref` if larger than 2 machine words.
No `@restrict` (IIUC, the LLVM semantics are more strict and
wouldn't allow the same arg to be passed as 2 `@restrict` refs,
even if both are const).
---
Wrt. the concerns about differing ref/value decisions for PODs
across compilers/platforms and thus implementation-dependent
potential aliasing issues for lvalue args: a possible approach
could be leaving everything as-is ABI-wise, but have the compiler
create and pass a temporary in @safe callers if the callee takes
a ref, unless it can prove there's no way the arg can be aliased.
E.g., assuming x87 `real` for Win64:
void callee(in real x); // e.g., by-ref for Win64, by-value for
Posix x86_64
void safeCaller1(ref x) @safe
{
callee(x); // x might be aliased by global state
// for Win64: auto tmp = x, callee(tmp);
// Posix x86_64: by-value, so simply `callee(x)`
}
void safeCaller2() @safe
{
real x = 1;
callee(x); // x cannot be aliased, fine to pass directly
by-ref for Win64
}
void safeCaller3(in real x) @safe
{
callee(x); // safe to forward directly by-ref for Win64
}
More information about the Digitalmars-d
mailing list