_argptr layout
Iain Buclaw
ibuclaw at ubuntu.com
Sun Jan 16 11:56:02 PST 2011
I guess I've always assumed it to be all values packed together and accessible
via moving the pointer forwards/backwards (like 32bit varargs), but is this
really true? Are all datatypes really expected to be a packed data structure? Or
are all varargs in D the exact same underpinnings as the C ABI for the platform
you're running on, but just encapsulated in a void*.
std.format is a prime example of this being the former, and the whole of tango
assumes so too (regardless of platform/architecture). The documentation tends to
agree with the former too, but is somewhat vague:
'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.'
But other than that, there's nothing else describing it. I know it can't be
passed as an argument, I know that it's only available for extern(D) linkage. But
what is it supposed to be?
This comes at a time where I'm sorting this out on gdc, see here for an idea of
the way I've done it: http://d.puremagic.com/issues/show_bug.cgi?id=670#c7
However there are quite a number of problems in phobos. For example, in
std.stream (a very condensed showing, comments are my own):
import std.stdarg; // for extern(D) linkage. va_list is a void*
size_t vprintf(const(char)[] format, va_list args) {
char[1024] buffer;
char* p = buffer.ptr;
auto f = toStringz(format);
size_t psize = buffer.length;
size_t count;
while (true) {
// calls extern(C) function vsnprintf that expects 'args'
// to be that of the target-specific type. Which could be char*,
// struct[1], or a ubyte[12][1]. However, we have void* ...
count = vsnprintf(p, psize, f, args);
if (count == -1)
psize *= 2;
else if (count >= psize)
psize = count + 1;
else
break;
p = cast(char*) alloca(psize);
}
writeString(p[0 .. count]);
return count;
}
It's rather bad enough that phobos rather dumbly assumes 32bit anyway. And 64bit
users have always complained that they can't do *cast(int*)_argptr in gdc. So
what exactly am I implementing here? I've actually had a good sit back from it
all for reflection and have only come up with the answer: 'You know, I honestly
don't know'.
Just need some clarification. :)
Regards
More information about the Digitalmars-d
mailing list