Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit fa0afa8

Browse files
committed
core.stdc.stdarg: Upstream GDC and LDC specifics
1 parent 583c6d0 commit fa0afa8

File tree

1 file changed

+82
-54
lines changed

1 file changed

+82
-54
lines changed

src/core/stdc/stdarg.d

Lines changed: 82 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ version (X86_64)
2222
else version = SysV_x64;
2323
}
2424

25-
version (SysV_x64)
25+
version (GNU)
26+
{
27+
import gcc.builtins;
28+
}
29+
else version (SysV_x64)
2630
{
2731
static import core.internal.vararg.sysv_x64;
2832

@@ -85,7 +89,12 @@ unittest
8589
/**
8690
* The argument pointer type.
8791
*/
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)
8998
{
9099
alias va_list = core.internal.vararg.sysv_x64.va_list;
91100
public import core.internal.vararg.sysv_x64 : __va_list, __va_list_tag;
@@ -116,60 +125,56 @@ else version (AAPCS64)
116125
}
117126
else
118127
{
119-
alias va_list = char*;
128+
alias va_list = char*; // incl. unknown platforms
120129
}
121130

122131

123132
/**
124133
* 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.
127135
*/
128-
version (X86)
136+
version (GNU)
129137
{
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);
134139
}
135-
else
140+
else version (LDC)
136141
{
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;
138144
}
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)
145146
{
146147
version (X86)
147148
{
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+
}
160153
}
161154
else
162155
{
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
166157
}
167158
}
168159

169160

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+
170172
/**
171173
* Retrieve and store in parmn the next value that is of type T.
172174
*/
175+
version (GNU)
176+
void va_arg(T)(ref va_list ap, ref T parmn); // intrinsic
177+
else
173178
void va_arg(T)(ref va_list ap, ref T parmn)
174179
{
175180
version (X86)
@@ -246,6 +251,7 @@ void va_arg(T)(ref va_list ap, ref T parmn)
246251
* Retrieve and store through parmn the next value that is of TypeInfo ti.
247252
* Used when the static type is not known.
248253
*/
254+
version (GNU) { /* unsupported */ } else
249255
void va_arg()(ref va_list ap, TypeInfo ti, void* parmn)
250256
{
251257
version (X86)
@@ -323,34 +329,56 @@ void va_arg()(ref va_list ap, TypeInfo ti, void* parmn)
323329
/**
324330
* End use of ap.
325331
*/
326-
void va_end(va_list ap)
332+
version (GNU)
333+
{
334+
alias va_end = __builtin_va_end;
335+
}
336+
else version (LDC)
327337
{
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) {}
328344
}
329345

330346

331-
// va_copy
332-
version (SysV_x64)
347+
/**
348+
* Make a copy of ap.
349+
*/
350+
version (GNU)
333351
{
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;
348353
}
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)
350360
{
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
353378
{
354-
dest = src;
379+
void va_copy(out va_list dest, va_list src)
380+
{
381+
dest = src;
382+
}
355383
}
356384
}

0 commit comments

Comments
 (0)