www.digitalmars.com         C & C++   DMDScript  

D.gnu - va_list ARM changes

reply Johannes Pfau <nospam example.com> writes:
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
--------
Aug 31 2012
next sibling parent Iain Buclaw <ibuclaw ubuntu.com> writes:
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';
Aug 31 2012
prev sibling next sibling parent Johannes Pfau <nospam example.com> writes:
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.
 

that va_arg overload and as the templated version works fine anyway it doesn't matter.
Aug 31 2012
prev sibling parent Iain Buclaw <ibuclaw ubuntu.com> writes:
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.

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';
Aug 31 2012