Jump to page: 1 2 3
Thread overview
_argptr woes
Mar 17, 2007
kris
Mar 17, 2007
Frits van Bommel
Mar 17, 2007
Bill Baxter
Mar 17, 2007
Sean Kelly
Mar 17, 2007
Sean Kelly
Mar 17, 2007
Frits van Bommel
Mar 17, 2007
Lars Ivar Igesund
Mar 17, 2007
Frits van Bommel
Mar 17, 2007
Lars Ivar Igesund
Mar 17, 2007
Frits van Bommel
Mar 17, 2007
Sean Kelly
Mar 17, 2007
Sean Kelly
Mar 17, 2007
Frits van Bommel
Mar 17, 2007
Sean Kelly
_argptr woes -- RFC from Walter
Mar 17, 2007
kris
Mar 17, 2007
Frits van Bommel
Mar 17, 2007
kris
Mar 17, 2007
Frits van Bommel
Mar 17, 2007
kris
Mar 17, 2007
Frits van Bommel
Mar 20, 2007
kris
Mar 17, 2007
Daniel Keep
Mar 17, 2007
Frits van Bommel
March 17, 2007
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?
March 17, 2007
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)
March 17, 2007
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)

Sounds like a good opportunity to replace the whole _argptr/_arguments hack with something more D-like.  Something more like a TypeInfo.  Say,  a VarArgInfo class which provides slightly higher level access to the void*/TypeInfo[] pair.  Then make it possible to use that as the last argument to the vararg function:

    int foo(char[] fmt, ... v) {
        // v is a VarArgInfo here
    }

Nice thing is this can coexist with _argptr/_arguments code.  If you don't specify a variable name for the vararg, you get _argptr/_arguments behavior.  If you do specify then you get a VarArgInfo with the specified name.

--bb
March 17, 2007
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.


Sean
March 17, 2007
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.  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.

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/


Sean
March 17, 2007

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.
> 
> 
> Sean

I imagine it's more a case of: "here's an ABI we came up with for our new architecture--you don't have to use it, but wouldn't it be nice if we all just got along?"

If nothing else, it gives everyone a common calling convention to implement so that their language can do interop on that platform easily.

	-- Daniel

-- 
Unlike Knuth, I have neither proven or tried the above; it may not even make sense.

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
March 17, 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?
March 17, 2007
Daniel Keep wrote:
> 
> Sean Kelly wrote:
>> Frits van Bommel wrote:
>>> 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 don't think it's a CPU spec, it's just a document written in an attempt to make sure compilers for a new architecture are (somewhat) compatible.

> I imagine it's more a case of: "here's an ABI we came up with for our
> new architecture--you don't have to use it, but wouldn't it be nice if
> we all just got along?"

Yeah, looks like. And AFAICT it's pretty good, but the vararg calling convention sucks. This probably has to do with unprototyped C functions, since those can be both normal and vararg functions. So they made sure the calling convention remains compatible, screwing everyone else using it over :(.

> If nothing else, it gives everyone a common calling convention to
> implement so that their language can do interop on that platform easily.

Which is always a good idea. Especially when the majority of developers probably come from a register-starved platform (x86) where the "default" calling convention is pretty much stack-only, and the new architecture has extra registers that can be used to handle this more efficiently.
March 17, 2007
Frits van Bommel wrote:

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

Rather that that code breaks because GDC don't follow the D ABI :)

-- 
Lars Ivar Igesund
blog at http://larsivi.net
DSource, #d.tango & #D: larsivi
Dancing the Tango
March 17, 2007
Lars Ivar Igesund wrote:
> Frits van Bommel wrote:
> 
>> [2]: At least, I presume this discussion was brought on by the
>> non-portable code in tango.text.convert.Layout?
> 
> Rather that that code breaks because GDC don't follow the D ABI :)

You may notice that the same text that specifies _argptr should be a void* then goes on to say[1] "To protect against the vagaries of stack layouts on different CPU architectures, use std.stdarg to access the variadic arguments".
Doesn't this pretty much mean there's no good reason for _argptr to be a void* instead of a CPU-specific va_list type as declared by std.stdarg, which would be aliased to whatever the appropriate type for the CPU architecture is. (i.e. gcc.builtins.__builtin_va_list for GDC, void* for DMD)

In short: I don't think GDC is broken here, the ABI is just still a bit x86-centric and is the one that should be fixed. There is simply no good reason to decide in the standard that _argptr must be a pointer. It may be simpler (compiler) implementation-wise, but if you can't portably use the pointer anyway you may as well leave _argptr's type up to the compiler and just specify it as std.vararg.va_list, whatever that may be.


[1]: At the end of the section, after an example using manual pointer casting that seems to carefully avoid parameter types smaller than int.sizeof...
« First   ‹ Prev
1 2 3