One minute to twelve: last chance to fix D2 ABI?

Lionello Lunesu lio at lunesu.remove.com
Tue Mar 2 18:02:51 PST 2010


The following has been discussed for years, and the biggest problem
(years ago) was that it was too late to change the D (1) ABI.

Is the D2 ABI compatible with D1? Should it be? If not, please consider
the following change:

alias void delegate() action_d;
void Callback() { }             // global
action_d = &Callback;           // should work

A function should be assignable to a delegate (but not vice versa*.)
This can work, since the code invoking the delegate will end up calling
the function with a context pointer ("this") in a register that's simply
ignored by the code in the function.

This is fairly easy too: the calling convention for functions and
delegates should be identical, except for the context pointer, which
should be stored in a register that's unused in the function calling
convention.

The reason for this change is that many times classes expose delegates
for callbacks, but it's impossible to bind a function to those
delegates. The code above can easily be made to compile:

action_d = { Callback(); }; //wrapped, works

but causes a dummy function to be called, only because the parameter
ABI's don't overlap:

_D1t4mainFZi12__dgliteral1MFZi  comdat            ;delegate literal
        assume  CS:_D1t4mainFZi12__dgliteral1MFZi
L0:             push    EAX
                call    near ptr _D1t8FunctionFZi ;global function
                pop     ECX
                ret
_D1t4mainFZi12__dgliteral1MFZi  ends

Of course, all of this applies to extern "D" code only.

* Binding a delegate to a function pointer will always need a (dynamic)
thunk, because the function will have been invoked without any context
pointer and it's the thunk's responsibility to assign the correct
context pointer.



More information about the Digitalmars-d mailing list