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

Lionello Lunesu lio at lunesu.remove.com
Wed Mar 3 02:28:46 PST 2010


On 3-3-2010 10:49, Robert Jacques wrote:
> On Tue, 02 Mar 2010 21:02:51 -0500, Lionello Lunesu
> <lio at lunesu.remove.com> wrote:
>> 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.
> 
> Except this also effects member functions, nested functions, etc.

Well, yes. That doesn't make it any harder or less possible.

>> 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.
> 
> This breaks the synergy of returns in EAX and params in EAX.

How exactly? I don't understand. What does the return value have to do
with any of this?

>> 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.
> 
> It would be fairly easy for D (or anyone else) to implicitly define a
> simple adapter that stores the function pointer in the delegate's this
> pointer. The adapter function pointer points to one of two common stub
> functions which either calls the this pointer or pops a value off the
> stack into EAX and then calls the this pointer.

It is easy. Like I should, you could just enter a pair of {} and it
would work. And to prevent context capturing (and heap allocation) you
could use such an adapter function. But without changing the ABI, even
in the best case you would have a wrapper function with an extra call
operation, which simply should not be necessary.

L.



More information about the Digitalmars-d mailing list