simple ABI change to enable implicit conversion of functions to delegates?
kinke via Digitalmars-d
digitalmars-d at puremagic.com
Mon May 15 05:27:10 PDT 2017
On Monday, 15 May 2017 at 10:41:55 UTC, ag0aep6g wrote:
> TL;DR: Changing the ABI of delegates so that the context
> pointer is passed last would make functions implicitly
> convertible to delegates, no?
>
> In the discussion of issue 17156 [1], Eyal asks why functions
> (function pointers?) don't convert implicitly to delegates.
> Walter's answer is that their ABIs differ and that a wrapper
> would have to be generated to treat a function transparently as
> a delegate.
>
> As far as I understand, the problem is that the hidden context
> pointer of a delegate takes the first register, pushing the
> other parameters back. That means the visible arguments are
> passed in different registers than when calling a function.
>
> Some code to show this:
>
> ----
> void delegate(int a, int b) dg;
> void f(int a, int b) { import std.stdio; writeln(a, " ", b); }
>
> void main()
> {
> dg.funcptr = &f; /* This line should probably not compile,
> but that's
> another story. */
> dg.ptr = cast(void*) 13;
> f(1, 2); /* prints "1 2" - no surprise */
> dg(1, 2); /* prints "2 13" */
> }
> ----
>
> Arguments are put into registers in reverse order. I.e., in a
> sense, the call `f(1, 2)` passes (2, 1) to f. And the call
> `dg(1, 2)` passes (13, 2, 1), because a delegate has a hidden
> last parameter: the context pointer. But `f` isn't compiled
> with such a hidden parameter, so it sees 13 in `b` and 2 in
> `a`. The register that holds 1 is simply ignored because
> there's no corresponding parameter.
>
> Now, what if we changed the ABI of delegates so that the
> context pointer is passed after the explicit arguments? That
> is, `dg(1, 2)` would pass (2, 1, 13). Then `f` would see 2 in b
> and 1 in a. It would ignore 13. Seems everything would just
> work then.
>
> This seems quite simple. But I'm most probably just too
> ignorant to see the problems. Why wouldn't this work? Maybe
> there's a reason why the context pointer has to be passed first?
>
>
>
> [1] https://issues.dlang.org/show_bug.cgi?id=17156
First of all, please don't forget that we're not only targeting
X86, and that the args, according to the docs, shouldn't actually
be reversed (incl. extern(D) - just on Win32, everywhere else the
C ABI is to be followed).
Then some ABIs, like Microsoft's, treat ` this` in a special way,
not just like any other argument (in combination with
struct-return), which would apply to method calls via a delegate
with context = object reference.
Some additional context: https://github.com/dlang/dmd/pull/5232
More information about the Digitalmars-d
mailing list