On 26.06.2016 20:08, Iain Buclaw via Digitalmars-d wrote:
On 26 June 2016 at 14:33, Timon Gehr via Digitalmars-d
<[email protected]> wrote:
On 26.06.2016 10:08, Iain Buclaw via Digitalmars-d wrote:

Old codegen:

_base = *(getBase());
_lwr = getLowerBound(_base.length);
_upr = getUpperBound(_base.length);
r = {.length=(_upr - _lwr), .ptr=_base.ptr + _lwr * 4};

---


This seems to be what I'd expect. It's also what CTFE does.
CTFE and run time behaviour should be identical. (So either one of them
needs to be fixed.)



Very likely CTFE.  Anyway, this isn't the only thing where CTFE and
Runtime do things differently.
...

All arbitrary differences should be eradicated.

Now when creating temporaries of references, the reference is stabilized
instead.

New codegen:

*(_ptr = getBase());
_lwr = getLowerBound(_ptr.length);
_upr = getUpperBound(_ptr.length);
r = {.length=(_upr - _lwr), .ptr=_ptr.ptr + _lwr * 4};
---

I suggest you fix LDC if it doesn't already do this. :-)



I'm not convinced this is a good idea. It makes (()=>base)()[lwr()..upr()]
behave differently from base[lwr()..upr()].

No, sorry, I'm afraid you are wrong there. They should both behave
exactly the same.
...

I don't see how that is possible, unless I misunderstood your previous explanation. As far as I understand, for the first expression, code gen will generate a reference to a temporary copy of base, and for the second expression, it will generate a reference to base directly. If lwr() or upr() then update the ptr and/or the length of base, those changes will be seen for the second slice expression, but not for the first.


I may need to step aside and explain what changed in GDC, as it had
nothing to do with this LDC bug.

==> Step

What made this subtle change was in relation to fixing bug 42 and 228
in GDC, which involved turning on TREE_ADDRESSABLE(type) bit in our
codegen trees, which in turn makes NRVO work consistently regardless
of optimization flags used - no more optimizer being confused by us
"faking it".

How is the above jargon related? Well, one of the problems faced was
that it must be ensured that lvalues continue being lvalues when
considering creating a temporary in the codegen pass.  Lvalue
references must have the reference stabilized, not the value that is
being dereferenced.  This also came with an added assurance that GDC
will now *never* create a temporary of a decl with a cpctor or dtor,
else it'll die with an internal compiler error trying. :-)
...

What is the justification why the base should be evaluated as an lvalue?

<== Step

(() => base)[lwr()..up()] will make a temporary of (() => base), but
guarantees that references are stabilized first.


(I assume you meant (() => base)()[lwr()..upr()].)

The lambda returns by value, so you will stabilize the reference to a temporary copy of base? (Unless I misunderstand your terminology.)

base[lwr()..upr()] will create no temporary if base has no side
effects.  And so if lwr() modifies base, then upr() will get the
updated copy.


Yes, it is clear that upr() should see modifications to memory that lwr() makes. The point is that the slice expression itself does or does not see the updates based on whether I wrap base in a lambda or not.



Reply via email to