@@ -22,7 +22,11 @@ version (X86_64)
22
22
else version = SysV_x64;
23
23
}
24
24
25
- version (SysV_x64)
25
+ version (GNU )
26
+ {
27
+ import gcc.builtins;
28
+ }
29
+ else version (SysV_x64)
26
30
{
27
31
static import core.internal.vararg.sysv_x64 ;
28
32
@@ -85,7 +89,12 @@ unittest
85
89
/**
86
90
* The argument pointer type.
87
91
*/
88
- version (SysV_x64)
92
+ version (GNU )
93
+ {
94
+ alias va_list = __gnuc_va_list;
95
+ alias __gnuc_va_list = __builtin_va_list;
96
+ }
97
+ else version (SysV_x64)
89
98
{
90
99
alias va_list = core.internal.vararg.sysv_x64.va_list ;
91
100
public import core.internal.vararg.sysv_x64 : __va_list, __va_list_tag;
@@ -116,60 +125,56 @@ else version (AAPCS64)
116
125
}
117
126
else
118
127
{
119
- alias va_list = char * ;
128
+ alias va_list = char * ; // incl. unknown platforms
120
129
}
121
130
122
131
123
132
/**
124
133
* Initialize ap.
125
- * parmn should be the last named parameter;
126
- * for DMD and non-Windows x86_64 targets, it should be __va_argsave.
134
+ * parmn should be the last named parameter.
127
135
*/
128
- version (X86 )
136
+ version (GNU )
129
137
{
130
- void va_start (T)(out va_list ap, ref T parmn)
131
- {
132
- ap = cast (va_list) ((cast (void * ) &parmn) + T.sizeof.alignUp);
133
- }
138
+ void va_start (T)(out va_list ap, ref T parmn);
134
139
}
135
- else
140
+ else version ( LDC )
136
141
{
137
- void va_start (T)(out va_list ap, ref T parmn); // Compiler intrinsic
142
+ pragma (LDC_va_start)
143
+ void va_start (T)(out va_list ap, ref T parmn) @nogc ;
138
144
}
139
-
140
-
141
- /**
142
- * Retrieve and return the next value that is of type T.
143
- */
144
- T va_arg (T)(ref va_list ap)
145
+ else version (DigitalMars )
145
146
{
146
147
version (X86 )
147
148
{
148
- T arg = * cast (T* ) ap;
149
- ap += T.sizeof.alignUp;
150
- return arg;
151
- }
152
- else version (Win64 )
153
- {
154
- static if (T.sizeof > size_t .sizeof)
155
- T arg = ** cast (T** ) ap;
156
- else
157
- T arg = * cast (T* ) ap;
158
- ap += size_t .sizeof;
159
- return arg;
149
+ void va_start (T)(out va_list ap, ref T parmn)
150
+ {
151
+ ap = cast (va_list) ((cast (void * ) &parmn) + T.sizeof.alignUp);
152
+ }
160
153
}
161
154
else
162
155
{
163
- T a;
164
- va_arg(ap, a);
165
- return a;
156
+ void va_start (T)(out va_list ap, ref T parmn); // intrinsic; parmn should be __va_argsave for non-Windows x86_64 targets
166
157
}
167
158
}
168
159
169
160
161
+ /**
162
+ * Retrieve and return the next value that is of type T.
163
+ */
164
+ T va_arg (T)(ref va_list ap)
165
+ {
166
+ T a;
167
+ va_arg(ap, a);
168
+ return a;
169
+ }
170
+
171
+
170
172
/**
171
173
* Retrieve and store in parmn the next value that is of type T.
172
174
*/
175
+ version (GNU )
176
+ void va_arg (T)(ref va_list ap, ref T parmn); // intrinsic
177
+ else
173
178
void va_arg (T)(ref va_list ap, ref T parmn)
174
179
{
175
180
version (X86 )
@@ -246,6 +251,7 @@ void va_arg(T)(ref va_list ap, ref T parmn)
246
251
* Retrieve and store through parmn the next value that is of TypeInfo ti.
247
252
* Used when the static type is not known.
248
253
*/
254
+ version (GNU ) { /* unsupported */ } else
249
255
void va_arg ()(ref va_list ap, TypeInfo ti, void * parmn)
250
256
{
251
257
version (X86 )
@@ -323,34 +329,56 @@ void va_arg()(ref va_list ap, TypeInfo ti, void* parmn)
323
329
/**
324
330
* End use of ap.
325
331
*/
326
- void va_end (va_list ap)
332
+ version (GNU )
333
+ {
334
+ alias va_end = __builtin_va_end;
335
+ }
336
+ else version (LDC )
327
337
{
338
+ pragma (LDC_va_end)
339
+ void va_end (va_list ap);
340
+ }
341
+ else version (DigitalMars )
342
+ {
343
+ void va_end (va_list ap) {}
328
344
}
329
345
330
346
331
- // va_copy
332
- version (SysV_x64)
347
+ /**
348
+ * Make a copy of ap.
349
+ */
350
+ version (GNU )
333
351
{
334
- import core.stdc.stdlib : alloca;
335
-
336
- // /
337
- void va_copy (out va_list dest, va_list src, void * storage = alloca(__va_list_tag.sizeof))
338
- {
339
- // Instead of copying the pointers, and aliasing the source va_list,
340
- // the default argument alloca will allocate storage in the caller's
341
- // stack frame. This is still not correct (it should be allocated in
342
- // the place where the va_list variable is declared) but most of the
343
- // time the caller's stack frame _is_ the place where the va_list is
344
- // allocated, so in most cases this will now work.
345
- dest = cast (va_list) storage;
346
- * dest = * src;
347
- }
352
+ alias va_copy = __builtin_va_copy;
348
353
}
349
- else
354
+ else version (LDC )
355
+ {
356
+ pragma (LDC_va_copy)
357
+ void va_copy (out va_list dest, va_list src);
358
+ }
359
+ else version (DigitalMars )
350
360
{
351
- // /
352
- void va_copy (out va_list dest, va_list src)
361
+ version (SysV_x64)
362
+ {
363
+ void va_copy (out va_list dest, va_list src, void * storage = alloca(__va_list_tag.sizeof))
364
+ {
365
+ // Instead of copying the pointers, and aliasing the source va_list,
366
+ // the default argument alloca will allocate storage in the caller's
367
+ // stack frame. This is still not correct (it should be allocated in
368
+ // the place where the va_list variable is declared) but most of the
369
+ // time the caller's stack frame _is_ the place where the va_list is
370
+ // allocated, so in most cases this will now work.
371
+ dest = cast (va_list) storage;
372
+ * dest = * src;
373
+ }
374
+
375
+ import core.stdc.stdlib : alloca;
376
+ }
377
+ else
353
378
{
354
- dest = src;
379
+ void va_copy (out va_list dest, va_list src)
380
+ {
381
+ dest = src;
382
+ }
355
383
}
356
384
}
0 commit comments