Thread overview
va_list ARM changes
Aug 31, 2012
Johannes Pfau
Aug 31, 2012
Iain Buclaw
Aug 31, 2012
Johannes Pfau
Aug 31, 2012
Iain Buclaw
August 31, 2012
I tested the changes as in revision 59f52c69d79b10c81913e837ecb14dad0c5fe264:

I wasn't sure what exactly should be tested, this is the test case I
used: http://dpaste.dzfl.pl/c362e632
(not sure why it doesn't compile on dpaste, it works with my local dmd
and gdc installation)
This was the output:
--------
foo
Test test 42
-0.481002
42 Hello [10, 0, 0, 0, 200, 69, 246, 190, 0, 1]
--------

* Formatting the struct works, the vprintf example works as well.

* Test2 fails, the float is not read correctly. Could be related to the
  hardfloat API? (it does work on x86 dmd, can't text x86 gdc right
  now). More complicated examples with floats usually lead to
  segmentation faults.

* Test3 does not work either. Seems passing static arrays doesn't work.
  However, this also doesn't work on x86/dmd so maybe I'm doing
  something wrong?
  It seems this is alignment related though: I guess va_arg always
  expects the arguments to be aligned, but ubyte[10] isn't aligned?
  If the value passed to the function is a ulong, but read as a ubyte[8]
  everything is fine (on arm and on x86/dmd), if the value is passed
  as a ubyte[8] and read as a ubyte[8] it doesn't work:
--------
    ubyte[8] c = cast(ubyte[8])[0,1,2,3,4,5,6,7];
    test3("", 42, "Hello", *(cast(ulong*)&c)); //WORKS
--------
August 31, 2012
On 31 August 2012 11:28, Johannes Pfau <nospam@example.com> wrote:
> I tested the changes as in revision 59f52c69d79b10c81913e837ecb14dad0c5fe264:
>
> I wasn't sure what exactly should be tested, this is the test case I
> used: http://dpaste.dzfl.pl/c362e632
> (not sure why it doesn't compile on dpaste, it works with my local dmd
> and gdc installation)
> This was the output:
> --------
> foo
> Test test 42
> -0.481002
> 42 Hello [10, 0, 0, 0, 200, 69, 246, 190, 0, 1]
> --------
>

Part of where you are going wrong is that 'va_arg (va_list, TypeInfo, void*)' should only be used when the static type is indeterminable. This is typically only for structs and classes.  All basic types should go through the normal va_arg template functions - these actually get expanded intrinsically by the gcc backend and *do* the right thing, even for your float example.

Now that is not to say that you can't use 'va_arg (va_list, TypeInfo, void*)' for basic types, but you do need to be aware of type promotions when it comes to va_args. :-)

Eg:

void main()
{
  test2("", cast(float)3.45f, "TestTest");  // float is promoted to
double when passed as a vararg.
}

void test2(string input, ...)
{
  double f;
  string s;
  va_list list;
  va_start(list, input);
  va_arg(list, typeid(typeof(f)), &f);
  va_arg(list, typeid(typeof(s)), &s);
  va_end(list);
  writefln("%s %s", f, s);
}


And you'll see that test2() in your paste works.

-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
August 31, 2012
Am Fri, 31 Aug 2012 12:49:37 +0100
schrieb Iain Buclaw <ibuclaw@ubuntu.com>:

> Part of where you are going wrong is that 'va_arg (va_list, TypeInfo, void*)' should only be used when the static type is indeterminable. This is typically only for structs and classes.  All basic types should go through the normal va_arg template functions - these actually get expanded intrinsically by the gcc backend and *do* the right thing, even for your float example.

OK, then everything is working as expected.
> 
> Now that is not to say that you can't use 'va_arg (va_list, TypeInfo, void*)' for basic types, but you do need to be aware of type promotions when it comes to va_args. :-)
> 
> Eg:
> 
> void main()
> {
>   test2("", cast(float)3.45f, "TestTest");  // float is promoted to
> double when passed as a vararg.
> }
> 
> void test2(string input, ...)
> {
>   double f;
>   string s;
>   va_list list;
>   va_start(list, input);
>   va_arg(list, typeid(typeof(f)), &f);
>   va_arg(list, typeid(typeof(s)), &s);
>   va_end(list);
>   writefln("%s %s", f, s);
> }
> 
> 
> And you'll see that test2() in your paste works.
> 
Still doesn't work for me, but if basic types should not be used with that va_arg overload and as the templated version works fine anyway it doesn't matter.

August 31, 2012
On 31 August 2012 13:05, Johannes Pfau <nospam@example.com> wrote:
> Am Fri, 31 Aug 2012 12:49:37 +0100
> schrieb Iain Buclaw <ibuclaw@ubuntu.com>:
>
>> Part of where you are going wrong is that 'va_arg (va_list, TypeInfo, void*)' should only be used when the static type is indeterminable. This is typically only for structs and classes.  All basic types should go through the normal va_arg template functions - these actually get expanded intrinsically by the gcc backend and *do* the right thing, even for your float example.
>
> OK, then everything is working as expected.
>>
>> Now that is not to say that you can't use 'va_arg (va_list, TypeInfo, void*)' for basic types, but you do need to be aware of type promotions when it comes to va_args. :-)
>>
>> Eg:
>>
>> void main()
>> {
>>   test2("", cast(float)3.45f, "TestTest");  // float is promoted to
>> double when passed as a vararg.
>> }
>>
>> void test2(string input, ...)
>> {
>>   double f;
>>   string s;
>>   va_list list;
>>   va_start(list, input);
>>   va_arg(list, typeid(typeof(f)), &f);
>>   va_arg(list, typeid(typeof(s)), &s);
>>   va_end(list);
>>   writefln("%s %s", f, s);
>> }
>>
>>
>> And you'll see that test2() in your paste works.
>>
> Still doesn't work for me, but if basic types should not be used with that va_arg overload and as the templated version works fine anyway it doesn't matter.
>

Boo!

I should have really brought my ARM device with me so I could test this... unfortunately I left it at home 300 miles away.


-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';