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