_argptr woes -- RFC from Walter

Frits van Bommel fvbommel at REMwOVExCAPSs.nl
Sat Mar 17 11:59:37 PDT 2007


kris 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?
> [snip]
>> [2]: At least, I presume this discussion was brought on by the 
>> non-portable code in tango.text.convert.Layout?
> 
> Indeed, although non-portable holds true only if you think in C instead 
> of D. According to the D documentation that code is written "correctly", 
> and thus it ought to be portable.

Assuming _argptr is a pointer and dereferencing it may be according to 
the spec as it is currently written, but that's not all the code does.
It also *increments* the pointer, at which time it _assumes_ all 
arguments are aligned at a multiple of int.sizeof (4). Even if varargs 
were entirely stack-based, that would likely break in the case of amd64 
since the most natural alignment for most parameters would be 8 (aka 
size_t.sizeof and (void*).sizeof). That's the size of anything a 'push' 
pushes and anything a 'pop' pops, as well as the size of return 
addresses. This could be 'fixed' for this case by using size_t or void*, 
but even that isn't guaranteed to work anywhere else.
Note that incrementing _argptr manually is discouraged:
"To protect against the vagaries of stack layouts on different CPU 
architectures, use std.stdarg to access the variadic arguments"
Nowhere on that page (that I can see) is the minimum alignment for 
arguments specified.
So even given that dereferencing the pointer may be portable, there's no 
way to portably increment it without using va_arg.
In fact, AFAICT it's not even guaranteed you need increment instead of 
decrement to get to the next argument (other than considerable 
difficulties / impossibility of implementing va_arg for that case).

So even though GDC may be going against the spec here, I'm still pretty 
sure that piece of code is not portable.



More information about the Digitalmars-d mailing list