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

Commit a9f9de4

Browse files
committed
core.stdc.vararg: Move implementation to va_arg version returning a value
This should be a prerequisite for fixing * https://issues.dlang.org/show_bug.cgi?id=20772 * https://issues.dlang.org/show_bug.cgi?id=20773
1 parent 4f7402d commit a9f9de4

File tree

2 files changed

+60
-54
lines changed

2 files changed

+60
-54
lines changed

src/core/internal/vararg/sysv_x64.d

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,16 @@ alias __va_list = __va_list_tag;
4343
alias va_list = __va_list*;
4444

4545
///
46-
void va_arg(T)(va_list apx, ref T parmn)
46+
T va_arg(T)(va_list ap)
4747
{
48-
__va_list* ap = cast(__va_list*) apx;
4948
static if (is(T U == __argTypes))
5049
{
5150
static if (U.length == 0 || T.sizeof > 16 || (U[0].sizeof > 8 && !is(U[0] == __vector)))
5251
{ // Always passed in memory
5352
// The arg may have more strict alignment than the stack
5453
void* p = ap.stack_args.alignUp!(T.alignof);
5554
ap.stack_args = p + T.sizeof.alignUp;
56-
parmn = *cast(T*) p;
55+
return *cast(T*) p;
5756
}
5857
else static if (U.length == 1)
5958
{ // Arg is passed in one register
@@ -62,35 +61,41 @@ void va_arg(T)(va_list apx, ref T parmn)
6261
{ // Passed in XMM register
6362
if (ap.offset_fpregs < (6 * 8 + 16 * 8))
6463
{
65-
parmn = *cast(T*) (ap.reg_args + ap.offset_fpregs);
64+
auto p = cast(T*) (ap.reg_args + ap.offset_fpregs);
6665
ap.offset_fpregs += 16;
66+
return *p;
6767
}
6868
else
6969
{
70-
parmn = *cast(T*) ap.stack_args;
70+
auto p = cast(T*) ap.stack_args;
7171
ap.stack_args += T1.sizeof.alignUp;
72+
return *p;
7273
}
7374
}
7475
else
7576
{ // Passed in regular register
7677
if (ap.offset_regs < 6 * 8 && T.sizeof <= 8)
7778
{
78-
parmn = *cast(T*) (ap.reg_args + ap.offset_regs);
79+
auto p = cast(T*) (ap.reg_args + ap.offset_regs);
7980
ap.offset_regs += 8;
81+
return *p;
8082
}
8183
else
8284
{
8385
void* p = ap.stack_args.alignUp!(T.alignof);
8486
ap.stack_args = p + T.sizeof.alignUp;
85-
parmn = *cast(T*) p;
87+
return *cast(T*) p;
8688
}
8789
}
8890
}
8991
else static if (U.length == 2)
9092
{ // Arg is passed in two registers
9193
alias U[0] T1;
9294
alias U[1] T2;
93-
auto p = (cast(void*) &parmn) + 8;
95+
96+
T result = void;
97+
auto p1 = cast(T1*) &result;
98+
auto p2 = cast(T2*) ((cast(void*) &result) + 8);
9499

95100
// Both must be in registers, or both on stack, hence 4 cases
96101

@@ -99,15 +104,15 @@ void va_arg(T)(va_list apx, ref T parmn)
99104
{
100105
if (ap.offset_fpregs < (6 * 8 + 16 * 8) - 16)
101106
{
102-
*cast(T1*) &parmn = *cast(T1*) (ap.reg_args + ap.offset_fpregs);
103-
*cast(T2*) p = *cast(T2*) (ap.reg_args + ap.offset_fpregs + 16);
107+
*p1 = *cast(T1*) (ap.reg_args + ap.offset_fpregs);
108+
*p2 = *cast(T2*) (ap.reg_args + ap.offset_fpregs + 16);
104109
ap.offset_fpregs += 32;
105110
}
106111
else
107112
{
108-
*cast(T1*) &parmn = *cast(T1*) ap.stack_args;
113+
*p1 = *cast(T1*) ap.stack_args;
109114
ap.stack_args += T1.sizeof.alignUp;
110-
*cast(T2*) p = *cast(T2*) ap.stack_args;
115+
*p2 = *cast(T2*) ap.stack_args;
111116
ap.stack_args += T2.sizeof.alignUp;
112117
}
113118
}
@@ -117,37 +122,37 @@ void va_arg(T)(va_list apx, ref T parmn)
117122
if (ap.offset_fpregs < (6 * 8 + 16 * 8) &&
118123
ap.offset_regs < 6 * 8 && T2.sizeof <= 8)
119124
{
120-
*cast(T1*) &parmn = *cast(T1*) (ap.reg_args + ap.offset_fpregs);
125+
*p1 = *cast(T1*) (ap.reg_args + ap.offset_fpregs);
121126
ap.offset_fpregs += 16;
122127
a = ap.reg_args + ap.offset_regs;
123128
ap.offset_regs += 8;
124129
}
125130
else
126131
{
127-
*cast(T1*) &parmn = *cast(T1*) ap.stack_args;
132+
*p1 = *cast(T1*) ap.stack_args;
128133
ap.stack_args += T1.sizeof.alignUp;
129134
a = ap.stack_args;
130135
ap.stack_args += 8;
131136
}
132137
// Be careful not to go past the size of the actual argument
133138
const sz2 = T.sizeof - 8;
134-
p[0..sz2] = a[0..sz2];
139+
(cast(void*) p2)[0..sz2] = a[0..sz2];
135140
}
136141
else static if (is(T2 == double) || is(T2 == float))
137142
{
138143
if (ap.offset_regs < 6 * 8 && T1.sizeof <= 8 &&
139144
ap.offset_fpregs < (6 * 8 + 16 * 8))
140145
{
141-
*cast(T1*) &parmn = *cast(T1*) (ap.reg_args + ap.offset_regs);
146+
*p1 = *cast(T1*) (ap.reg_args + ap.offset_regs);
142147
ap.offset_regs += 8;
143-
*cast(T2*) p = *cast(T2*) (ap.reg_args + ap.offset_fpregs);
148+
*p2 = *cast(T2*) (ap.reg_args + ap.offset_fpregs);
144149
ap.offset_fpregs += 16;
145150
}
146151
else
147152
{
148-
*cast(T1*) &parmn = *cast(T1*) ap.stack_args;
153+
*p1 = *cast(T1*) ap.stack_args;
149154
ap.stack_args += 8;
150-
*cast(T2*) p = *cast(T2*) ap.stack_args;
155+
*p2 = *cast(T2*) ap.stack_args;
151156
ap.stack_args += T2.sizeof.alignUp;
152157
}
153158
}
@@ -156,22 +161,24 @@ void va_arg(T)(va_list apx, ref T parmn)
156161
void* a = void;
157162
if (ap.offset_regs < 5 * 8 && T1.sizeof <= 8 && T2.sizeof <= 8)
158163
{
159-
*cast(T1*) &parmn = *cast(T1*) (ap.reg_args + ap.offset_regs);
164+
*p1 = *cast(T1*) (ap.reg_args + ap.offset_regs);
160165
ap.offset_regs += 8;
161166
a = ap.reg_args + ap.offset_regs;
162167
ap.offset_regs += 8;
163168
}
164169
else
165170
{
166-
*cast(T1*) &parmn = *cast(T1*) ap.stack_args;
171+
*p1 = *cast(T1*) ap.stack_args;
167172
ap.stack_args += 8;
168173
a = ap.stack_args;
169174
ap.stack_args += 8;
170175
}
171176
// Be careful not to go past the size of the actual argument
172177
const sz2 = T.sizeof - 8;
173-
p[0..sz2] = a[0..sz2];
178+
(cast(void*) p2)[0..sz2] = a[0..sz2];
174179
}
180+
181+
return result;
175182
}
176183
else
177184
{
@@ -185,9 +192,8 @@ void va_arg(T)(va_list apx, ref T parmn)
185192
}
186193

187194
///
188-
void va_arg()(va_list apx, TypeInfo ti, void* parmn)
195+
void va_arg()(va_list ap, TypeInfo ti, void* parmn)
189196
{
190-
__va_list* ap = cast(__va_list*) apx;
191197
TypeInfo arg1, arg2;
192198
if (!ti.argTypes(arg1, arg2))
193199
{

src/core/stdc/stdarg.d

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -167,26 +167,16 @@ else version (DigitalMars)
167167
/**
168168
* Retrieve and return the next value that is of type T.
169169
*/
170-
T va_arg(T)(ref va_list ap)
171-
{
172-
T a;
173-
va_arg(ap, a);
174-
return a;
175-
}
176-
177-
178-
/**
179-
* Retrieve and store in parmn the next value that is of type T.
180-
*/
181170
version (GNU)
182-
void va_arg(T)(ref va_list ap, ref T parmn); // intrinsic
171+
T va_arg(T)(ref va_list ap); // intrinsic
183172
else
184-
void va_arg(T)(ref va_list ap, ref T parmn)
173+
T va_arg(T)(ref va_list ap)
185174
{
186175
version (X86)
187176
{
188-
parmn = *cast(T*) ap;
177+
auto p = cast(T*) ap;
189178
ap += T.sizeof.alignUp;
179+
return *p;
190180
}
191181
else version (Win64)
192182
{
@@ -195,47 +185,48 @@ void va_arg(T)(ref va_list ap, ref T parmn)
195185
else enum isLDC = false;
196186
static if (isLDC && is(T == E[], E))
197187
{
198-
const length = *cast(size_t*) ap;
199-
ap += size_t.sizeof;
200-
auto ptr = *cast(typeof(parmn.ptr)*) ap;
201-
parmn = ptr[0 .. length];
188+
auto p = cast(T*) ap;
189+
ap += T.sizeof;
190+
return *p;
202191
}
192+
203193
// passed indirectly by value if > 64 bits or of a size that is not a power of 2
204-
else static if (T.sizeof > size_t.sizeof || (T.sizeof & (T.sizeof - 1)) != 0)
205-
parmn = **cast(T**) ap;
194+
static if (T.sizeof > size_t.sizeof || (T.sizeof & (T.sizeof - 1)) != 0)
195+
auto p = *cast(T**) ap;
206196
else
207-
parmn = *cast(T*) ap;
197+
auto p = cast(T*) ap;
208198
ap += size_t.sizeof;
199+
return *p;
209200
}
210201
else version (SysV_x64)
211202
{
212-
core.internal.vararg.sysv_x64.va_arg!T(ap, parmn);
203+
return core.internal.vararg.sysv_x64.va_arg!T(ap);
213204
}
214205
else version (AAPCS32)
215206
{
216207
// AAPCS32 section 6.5 B.5: type with alignment >= 8 is 8-byte aligned
217208
// instead of normal 4-byte alignment (APCS doesn't do this).
218209
if (T.alignof >= 8)
219210
ap.__ap = ap.__ap.alignUp!8;
220-
auto p = ap.__ap;
211+
auto p = cast(T*) ap.__ap;
221212
version (BigEndian)
222213
static if (T.sizeof < size_t.sizeof)
223214
p = adjustForBigEndian(p, T.sizeof);
224-
parmn = *cast(T*) p;
225215
ap.__ap += T.sizeof.alignUp;
216+
return *p;
226217
}
227218
else version (AAPCS64)
228219
{
229220
static assert(0, "Unsupported platform");
230221
}
231222
else version (ARM_Any)
232223
{
233-
auto p = ap;
224+
auto p = cast(T*) ap;
234225
version (BigEndian)
235226
static if (T.sizeof < size_t.sizeof)
236227
p = adjustForBigEndian(p, T.sizeof);
237-
parmn = *cast(T*) p;
238228
ap += T.sizeof.alignUp;
229+
return *p;
239230
}
240231
else version (PPC_Any)
241232
{
@@ -249,27 +240,36 @@ void va_arg(T)(ref va_list ap, ref T parmn)
249240
// be aligned before accessing a value
250241
if (T.alignof >= 8)
251242
ap = ap.alignUp!8;
252-
auto p = ap;
243+
auto p = cast(T*) ap;
253244
version (BigEndian)
254245
static if (T.sizeof < size_t.sizeof)
255246
p = adjustForBigEndian(p, T.sizeof);
256-
parmn = *cast(T*) p;
257247
ap += T.sizeof.alignUp;
248+
return *p;
258249
}
259250
else version (MIPS_Any)
260251
{
261-
auto p = ap;
252+
auto p = cast(T*) ap;
262253
version (BigEndian)
263254
static if (T.sizeof < size_t.sizeof)
264255
p = adjustForBigEndian(p, T.sizeof);
265-
parmn = *cast(T*) p;
266256
ap += T.sizeof.alignUp;
257+
return *p;
267258
}
268259
else
269260
static assert(0, "Unsupported platform");
270261
}
271262

272263

264+
/**
265+
* Retrieve and store in parmn the next value that is of type T.
266+
*/
267+
void va_arg(T)(ref va_list ap, ref T parmn)
268+
{
269+
parmn = va_arg!T(ap);
270+
}
271+
272+
273273
/**
274274
* End use of ap.
275275
*/

0 commit comments

Comments
 (0)