_argptr woes

Frits van Bommel fvbommel at REMwOVExCAPSs.nl
Sat Mar 17 03:38:42 PDT 2007


Sean Kelly wrote:
> Sean Kelly wrote:
>> Frits van Bommel wrote:
>>> kris wrote:
>>>> The D spec says:
>>>>
>>>> "The implementiations of these variadic functions have a special 
>>>> local variable declared for them, _argptr, which is a void* pointer 
>>>> to the first of the variadic arguments. To access the arguments, 
>>>> _argptr must be cast to a pointer to the expected argument type"
>>>>
>>>>
>>>> To me, this means that a D compiler must implement _argptr in these 
>>>> terms. Is that indeed the case, Walter? Or is my interpretation 
>>>> incorrect?
>>>
>>> That would seem to be what it means.
>>> That would also seem to be a pretty big portability bug in the spec. 
>>> On amd64 definitely !is(va_list == void*) :P. (at least for current 
>>> GDC, GCC and any other compiler following 
>>> http://www.x86-64.org/documentation/abi.pdf)
>>
>> Perhaps I'm being thick, but why in the world would a CPU spec need to 
>> contain parameter passing rules?  Or even stack frame information?  I 
>> can see an OS caring about stack frame, but parameter passing seems 
>> like it should be language-dependent.
> 
> I just answered my own question.  From the doc:
> 
>     No attempt has been made to specify an ABI for languages other than
>     C. However, it is assumed that many programming languages will wish
>     to link with code written in C, so that the ABI specifications
>     documented here apply there too.
> 
> So they define an ABI for C to facilitate interoperability across 
> compilers.  This is laudable, but it has nothing to do with calling D 
> functions.

At the moment it does, since GDC 0.23 seems to follow it on amd64...
(IIRC GDC just passes he context/this pointer (if any) as a hidden first 
argument, ensuring it'll always be in a register)
I would wholly support using a slight variation when it comes to varargs 
though, to put them in a contiguous area on the stack.

 > They also go on to say:
> 
>     The standard calling sequence requirements apply only to global
>     functions.  Local functions that are not reachable from other
>     compilation units may use different conventions. Nevertheless, it is
>     recommended that all functions use the standard calling sequence
>     when possible.

That just means you're free to do whatever optimizations on a per-module 
level with regards to calling functions only accessible from that module.

> By the way, this may be a more appropriate reference for D:
> 
>     For the C++ ABI we will use the IA-64 C++ ABI and instantiate it
>     appropriately.  The current draft of that ABI is available at:
>     http://www.codesourcery.com/cxx-abi/

 From what I can tell, this has the same fundamental problem: the first 
N parameters are stored in registers (if possible), even if they are 
varargs. (It seems to defer to the C ABI wrt varargs, and the 
corresponding C ABI[1] says to put 'em in registers as long as there's 
room (AFAICT))
It's slightly better in that only one set of registers is used for 
vararg parameters (vararg floats & doubles are passed in general-purpose 
registers) but that's about it. This may fix the immediate problem[2] 
though: parameter location is not so much dependent on type anymore, as 
long as D's value types remain free of non-trivial copy constructors & 
destructors. That means it may be possible to determine an argument 
location based solely on its size and position in the list.

Oh, but in order to be able to use this for amd64 you'd also have to 
define a new register mapping. (Note that IA-64 has *way* more registers 
than amd64, and seems to do some funky magic with them to rename most of 
them on calls)


[1]: available at http://www.intel.com/design/itanium/downloads/245358.htm

[2]: At least, I presume this discussion was brought on by the 
non-portable code in tango.text.convert.Layout?



More information about the Digitalmars-d mailing list