Tango 0.96 beta2 released
Frits van Bommel
fvbommel at REMwOVExCAPSs.nl
Fri Mar 16 16:02:44 PDT 2007
kris wrote:
> Frits van Bommel wrote:
> [snip]
>
> Thanks for digging into this, Frits
No problem. I assure you, it's mostly for selfish motives ;). I just
want it to work without having to resort to 32-bit compilers on a 64-bit
system.
(Though I get by with Phobos just fine)
>> [Fair warning: this seems to have become a pretty big post]
>> Unfortunately, that doesn't work. Specifically because of how Arg is
>> used in "public final uint convert (Sink sink, TypeInfo[] arguments,
>> Arg args, T[] formatStr)":
>> -----
>> Arg[64] arglist = void;
>> foreach (i, arg; arguments)
>> {
>> arglist[i] = args;
>> args += (arg.tsize + int.sizeof - 1) & ~ (int.sizeof - 1);
>> }
>>
>> return parse (formatStr, arguments, arglist, sink);
>> -----
>> Here it looks like it tries to manually extract the arguments,
>> assuming they all lie (on the stack) at int.sizeof boundaries. While
>> this may work on (32-bit?) platforms where varargs are all passed on
>> the stack like x86 with C or D calling convention[1], on amd64 this is
>> not the case: va_list isn't a pointer and the variable arguments
>> aren't necessarily all on the stack.
>
> Aye, it is intended to make each argument indexable.
That's what I thought.
I actually tried to change it to a more portable equivalent but gave up
once I realized that wasn't easily done without having access to the
actual types of the parameters at compile time.
> Only works on
> 32-bit platform, making the same assumptions as the code in std.stdarg
AFAICT only DMD's version of std.stdarg makes those assumptions. (And it
technically has every right to, since DMD is currently 32-bit only)
>> Since it seems GDC basically uses the C calling convention, I'll give
>> a short description of the problems I see with it:
>> The C(++?) calling convention on amd64[2] passes the first several
>> parameters in registers, and it seems not to deviate from this in case
>> of varargs. Worse, it uses different sets of registers for different
>> types of arguments (6 general-purpose registers for integer types &
>> pointers etc., 8 SSE regs for float/double, and the rest in memory).
>> Aggregates are potentially split up(!) if certain conditions are met
>> (< 16 bytes, all members are naturally aligned, fits entirely into
>> registers, and a few more).
>
> stdarg.d would fail also. That is not good :(
It shouldn't for the GDC version, I think.
Note these snippets from the code for std.stdarg distributed with GDC:
---
// va_arg is handled magically by the compiler
// [...]
template va_arg(T)
{
T va_arg(inout va_list _argptr)
{
/*
T arg = *cast(T*)_argptr;
_argptr = _argptr + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1));
return arg;
*/
T t; return t;
}
}
---
Note how little va_arg does (just enough to compile), and the comment
mentioning special compiler magic that presumably fixes it to do the
Right Thing(TM).
I haven't tried it out though, other than using writefln() in programs
and getting the expected output :).
More information about the Digitalmars-d-announce
mailing list