www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - _argptr layout

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
Jan 16 2011