@@ -26,7 +26,7 @@ T va_arg(T)(va_list ap)
2626{
2727 static if (is (T U == __argTypes))
2828 {
29- static if (U.length == 0 || U[0 ].sizeof > 8 || is (T1 == __vector ))
29+ static if (U.length == 0 || U[0 ].sizeof > 8 || is (U[ 0 ] == __vector ))
3030 {
3131 // Always passed in memory (varying vectors are passed in parameter area)
3232 auto p = * cast (T* ) ap.__overflow_arg_area;
@@ -45,7 +45,7 @@ T va_arg(T)(va_list ap)
4545 // Passed in $fr registers (FPR region starts at +0x80)
4646 auto p = cast (T* ) ap.__reg_save_area + 128 + ap.__fpr * 8 ;
4747 ap.__fpr++ ;
48- return p;
48+ return * p;
4949 }
5050 else
5151 {
@@ -54,7 +54,7 @@ T va_arg(T)(va_list ap)
5454 // no matter the actual size of the fp variable
5555 // parameter slot is always 8-byte-wide (f32 is extended to f64)
5656 ap.__overflow_arg_area += 8 ;
57- return p;
57+ return * p;
5858 }
5959 }
6060 else
@@ -65,7 +65,7 @@ T va_arg(T)(va_list ap)
6565 // Passed in $gpr registers (GPR region starts at +0x10)
6666 auto p = cast (T* ) ap.__reg_save_area + 16 + ap.__gpr * 8 ;
6767 ap.__gpr++ ;
68- return p;
68+ return * p;
6969 }
7070 else
7171 {
@@ -74,7 +74,7 @@ T va_arg(T)(va_list ap)
7474 // no matter the actual size of the gpr variable
7575 // parameter slot is always 8-byte-wide (after ABI adjustments)
7676 ap.__overflow_arg_area += 8 ;
77- return p;
77+ return * p;
7878 }
7979 }
8080 }
@@ -93,6 +93,23 @@ T va_arg(T)(va_list ap)
9393void va_arg ()(va_list ap, TypeInfo ti, void * parmn)
9494{
9595 TypeInfo arg1, arg2;
96+ if (TypeInfo_Struct ti_struct = cast (TypeInfo_Struct ) ti)
97+ {
98+ // handle single-float element struct
99+ const rtFields = ti_struct.offTi();
100+ if (rtFields && rtFields.length == 1 )
101+ {
102+ TypeInfo field1TypeInfo = rtFields[0 ].ti;
103+ if (field1TypeInfo is typeid (float ) || field1TypeInfo is typeid (double ))
104+ {
105+ auto tsize = field1TypeInfo.tsize;
106+ auto toffset = rtFields[0 ].offset;
107+ parmn[0 .. tsize] = p[toffset.. tsize];
108+ return ;
109+ }
110+ }
111+ }
112+
96113 if (! ti.argTypes(arg1, arg2))
97114 {
98115 TypeInfo_Vector v1 = arg1 ? cast (TypeInfo_Vector) arg1 : null ;
@@ -117,6 +134,30 @@ void va_arg()(va_list ap, TypeInfo ti, void* parmn)
117134 parmn[0 .. tsize] = p[0 .. tsize];
118135 }
119136 }
137+ else if (arg1 && (arg1 is typeid (float ) || arg1 is typeid (double )))
138+ {
139+ // Maybe passed in $fr registers
140+ if (ap.__fpr <= 4 )
141+ {
142+ // Passed in $fr registers (FPR region starts at +0x80)
143+ auto p = cast (T* ) ap.__reg_save_area + 128 + ap.__fpr * 8 ;
144+ ap.__fpr++ ;
145+ parmn[0 .. tsize] = p[0 .. tsize];
146+ }
147+ else
148+ {
149+ // overflow arguments
150+ auto p = cast (T* ) ap.__overflow_arg_area;
151+ // no matter the actual size of the fp variable
152+ // parameter slot is always 8-byte-wide (f32 is extended to f64)
153+ ap.__overflow_arg_area += 8 ;
154+ parmn[0 .. tsize] = p[0 .. tsize];
155+ }
156+ }
157+ else
158+ {
159+ assert (false , " unhandled va_arg type!" );
160+ }
120161 assert (! arg2);
121162 }
122163 else
0 commit comments