@@ -20,8 +20,6 @@ version ( PPC64 ) version = AnyPPC;
20
20
21
21
version ( X86_64 )
22
22
{
23
- version ( LDC ) version = LDC_X86_64 ;
24
-
25
23
// Determine if type is a vector type
26
24
template isVectorType (T)
27
25
{
@@ -295,7 +293,121 @@ version( X86_64 )
295
293
}
296
294
}
297
295
298
- version ( X86 )
296
+ version ( LDC )
297
+ {
298
+ // FIXME: This isn't actually tested at all for ARM.
299
+ // Really struct va_list { void* ptr; }, but for compatibility with
300
+ // x86-style code that uses char*, we just define it as the raw pointer.
301
+
302
+ version ( AnyPPC )
303
+ alias void * va_list;
304
+ else
305
+ alias char * va_list;
306
+
307
+ pragma (LDC_va_start)
308
+ void va_start (T)(va_list ap, ref T);
309
+
310
+ private pragma (LDC_va_arg)
311
+ T va_arg_impl (T)(va_list ap);
312
+
313
+ T va_arg (T)(ref va_list ap)
314
+ {
315
+ version ( Win64 )
316
+ {
317
+ static if (T.sizeof > size_t .sizeof || (T.sizeof & (T.sizeof - 1 )) != 0 )
318
+ T arg = ** cast (T** )ap;
319
+ else
320
+ T arg = * cast (T* )ap;
321
+ ap += size_t .sizeof;
322
+ return arg;
323
+ }
324
+ else version ( ARM )
325
+ {
326
+ T arg = * cast (T* )ap;
327
+ ap += (T.sizeof + size_t .sizeof - 1 ) & ~ (size_t .sizeof - 1 );
328
+ return arg;
329
+ }
330
+ else
331
+ return va_arg_impl! T(ap);
332
+ }
333
+
334
+ void va_arg (T)(ref va_list ap, ref T parmn)
335
+ {
336
+ version ( Win64 )
337
+ {
338
+ static if (T.sizeof > size_t .sizeof || (T.sizeof & (T.sizeof - 1 )) != 0 )
339
+ parmn = ** cast (T** )ap;
340
+ else
341
+ parmn = * cast (T* )ap;
342
+ ap += size_t .sizeof;
343
+ }
344
+ else version ( ARM )
345
+ {
346
+ parmn = * cast (T* )ap;
347
+ ap += (T.sizeof + size_t .sizeof - 1 ) & ~ (size_t .sizeof - 1 );
348
+ }
349
+ else
350
+ parmn = va_arg! T(ap);
351
+ }
352
+
353
+ void va_arg ()(ref va_list ap, TypeInfo ti, void * parmn)
354
+ {
355
+ auto tsize = ti.tsize;
356
+
357
+ version ( X86 )
358
+ {
359
+ // Wait until everyone updates to get TypeInfo.talign
360
+ // auto talign = ti.talign;
361
+ // auto p = cast(va_list) ((cast(size_t)ap + talign - 1) & ~(talign - 1));
362
+ auto p = ap;
363
+ ap = p + ((tsize + size_t .sizeof - 1 ) & ~ (size_t .sizeof - 1 ));
364
+ }
365
+ else version ( Win64 )
366
+ {
367
+ // passed byval if > 64 bits or not a power of 2
368
+ auto p = (tsize > size_t .sizeof || (tsize & (tsize - 1 )) != 0 ) ? * cast (char ** )ap : ap;
369
+ ap += size_t .sizeof;
370
+ }
371
+ else version ( X86_64 )
372
+ {
373
+ static assert (false , " core.stdc.stdarg.va_arg() not yet implemented for System V AMD64 ABI" );
374
+ }
375
+ else version ( ARM )
376
+ {
377
+ // Wait until everyone updates to get TypeInfo.talign
378
+ // auto talign = ti.talign;
379
+ // auto p = cast(va_list) ((cast(size_t)ap + talign - 1) & ~(talign - 1));
380
+ auto p = ap;
381
+ ap = p + ((tsize + size_t .sizeof - 1 ) & ~ (size_t .sizeof - 1 ));
382
+ }
383
+ else version ( AnyPPC )
384
+ {
385
+ /*
386
+ * The rules are described in the 64bit PowerPC ELF ABI Supplement 1.9,
387
+ * available here:
388
+ * http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html#PARAM-PASS
389
+ */
390
+
391
+ // This works for all types because only the rules for non-floating,
392
+ // non-vector types are used.
393
+ auto p = (tsize < size_t .sizeof ? ap + (size_t .sizeof - tsize) : ap);
394
+ ap += (tsize + size_t .sizeof - 1 ) & ~ (size_t .sizeof - 1 );
395
+ }
396
+ else
397
+ {
398
+ static assert (false , " Unsupported platform" );
399
+ }
400
+
401
+ parmn[0 .. tsize] = (cast (void * )p)[0 .. tsize];
402
+ }
403
+
404
+ pragma (LDC_va_end)
405
+ void va_end (va_list ap);
406
+
407
+ pragma (LDC_va_copy)
408
+ void va_copy (out va_list dest, va_list src);
409
+ }
410
+ else version ( X86 )
299
411
{
300
412
/* ********************
301
413
* The argument pointer type.
@@ -307,17 +419,9 @@ version( X86 )
307
419
* For 32 bit code, parmn should be the last named parameter.
308
420
* For 64 bit code, parmn should be __va_argsave.
309
421
*/
310
- version (LDC )
311
- {
312
- pragma (LDC_va_start)
313
- void va_start (T)(va_list ap, ref T);
314
- }
315
- else
422
+ void va_start (T)(out va_list ap, ref T parmn)
316
423
{
317
- void va_start (T)(out va_list ap, ref T parmn)
318
- {
319
- ap = cast (va_list)( cast (void * ) &parmn + ( ( T.sizeof + int .sizeof - 1 ) & ~ ( int .sizeof - 1 ) ) );
320
- }
424
+ ap = cast (va_list)( cast (void * ) &parmn + ( ( T.sizeof + int .sizeof - 1 ) & ~ ( int .sizeof - 1 ) ) );
321
425
}
322
426
323
427
/* ***********
@@ -368,151 +472,6 @@ version( X86 )
368
472
dest = src;
369
473
}
370
474
}
371
- else version ( ARM )
372
- {
373
- // FIXME: This isn't actually tested at all.
374
- // Really struct va_list { void* ptr; }, but for compatibility with
375
- // x86-style code that uses char*, we just define it as the raw pointer.
376
- alias va_list = char * ;
377
-
378
- version (LDC )
379
- {
380
- pragma (LDC_va_start)
381
- void va_start (T)(va_list ap, ref T);
382
- }
383
- else static assert (" Unsupported platform." );
384
-
385
- /**
386
- * Retrieve and return the next value that is type T.
387
- * This is the preferred version.
388
- */
389
- void va_arg (T)(ref va_list ap, ref T parmn)
390
- {
391
- parmn = * cast (T* )ap;
392
- ap = cast (va_list)(cast (void * )ap + ((T.sizeof + int .sizeof - 1 ) & ~ (int .sizeof - 1 )));
393
- }
394
-
395
- /**
396
- * Retrieve and store through parmn the next value that is of TypeInfo ti.
397
- * Used when the static type is not known.
398
- */
399
- void va_arg ()(ref va_list ap, TypeInfo ti, void * parmn)
400
- {
401
- // Wait until everyone updates to get TypeInfo.talign
402
- // auto talign = ti.talign;
403
- // auto p = cast(void*)(cast(size_t)ap + talign - 1) & ~(talign - 1);
404
- auto p = * cast (void ** ) ≈
405
- auto tsize = ti.tsize;
406
- * cast (void ** ) &ap += ((tsize + size_t .sizeof - 1 ) & ~ (size_t .sizeof - 1 ));
407
- parmn[0 .. tsize] = p[0 .. tsize];
408
- }
409
-
410
- /**
411
- * End use of ap.
412
- */
413
- void va_end (va_list ap)
414
- {
415
- }
416
-
417
- void va_copy (out va_list dest, va_list src)
418
- {
419
- dest = src;
420
- }
421
- }
422
- else version ( LDC_X86_64 )
423
- {
424
- version ( Win64 )
425
- {
426
- alias char * va_list;
427
-
428
- pragma (LDC_va_start)
429
- void va_start (T)(va_list ap, ref T);
430
-
431
- T va_arg (T)(ref va_list ap)
432
- {
433
- static if (T.sizeof > size_t .sizeof || (T.sizeof & (T.sizeof - 1 )) != 0 )
434
- T arg = ** cast (T** )ap;
435
- else
436
- T arg = * cast (T* )ap;
437
- ap += size_t .sizeof;
438
- return arg;
439
- }
440
-
441
- void va_arg (T)(ref va_list ap, ref T parmn)
442
- {
443
- static if (T.sizeof > size_t .sizeof || (T.sizeof & (T.sizeof - 1 )) != 0 )
444
- parmn = ** cast (T** )ap;
445
- else
446
- parmn = * cast (T* )ap;
447
- ap += size_t .sizeof;
448
- }
449
-
450
- void va_arg ()(ref va_list ap, TypeInfo ti, void * parmn)
451
- {
452
- // Wait until everyone updates to get TypeInfo.talign
453
- // auto talign = ti.talign;
454
- // auto p = (ap + talign - 1) & ~(talign - 1);
455
- auto p = ap;
456
- ap = p + size_t .sizeof;
457
- auto tsize = ti.tsize;
458
- void * q = (tsize > size_t .sizeof || (tsize & (tsize - 1 )) != 0 ) ? * cast (void ** )p : cast (void * )p;
459
- parmn[0 .. tsize] = q[0 .. tsize];
460
- }
461
-
462
- void va_end (va_list ap)
463
- {
464
- }
465
-
466
- void va_copy (out va_list dest, va_list src)
467
- {
468
- dest = src;
469
- }
470
- }
471
- else
472
- {
473
- // We absolutely need va_list to be something that causes the actual struct
474
- // to be passed by reference for compatibility with C function declarations.
475
- // Otherwise, e.g. "extern(C) int vprintf(const char*, va_list)" would fail
476
- // horribly. Now, with va_list = __va_list*, we can't properly implement
477
- // va_copy without cheating, as it needs to save the struct contents
478
- // somewhere (offset_regs, offset_fpregs), copying a pointer does not help.
479
- //
480
- // Currently, we just special-case va_start/va_copy when lowering the
481
- // pragmas and make them allocate the struct on the caller's stack. This
482
- // gets us 99% there for the common use cases. Eventually, the whole mess
483
- // will have to be cleaned up (also in DMD), probably by making va_list a
484
- // magic built-in type that on x86_64 decays to a reference like the actual
485
- // definition in C (one-element array), or by giving va_copy a different
486
- // signature.
487
- alias va_list = __va_list* ;
488
-
489
- pragma (LDC_va_start)
490
- void va_start (T)(out va_list ap, ref T);
491
-
492
- T va_arg (T)(va_list ap)
493
- {
494
- T a;
495
- va_arg(ap, a);
496
- return a;
497
- }
498
-
499
- void va_arg (T)(va_list apx, ref T parmn)
500
- {
501
- va_arg_x86_64(apx, parmn);
502
- }
503
-
504
- void va_arg ()(va_list apx, TypeInfo ti, void * parmn)
505
- {
506
- va_arg_x86_64(apx, ti, parmn);
507
- }
508
-
509
- pragma (LDC_va_end)
510
- void va_end (va_list ap);
511
-
512
- pragma (LDC_va_copy)
513
- void va_copy (out va_list dest, va_list src);
514
- }
515
- }
516
475
else version (Windows ) // Win64
517
476
{ /* Win64 is characterized by all arguments fitting into a register size.
518
477
* Smaller ones are padded out to register size, and larger ones are passed by
@@ -634,51 +593,6 @@ else version ( X86_64 )
634
593
dest = src;
635
594
}
636
595
}
637
- else version ( AnyPPC )
638
- {
639
- version ( LDC )
640
- {
641
- /*
642
- * The rules are described in the 64bit PowerPC ELF ABI Supplement 1.9,
643
- * available here:
644
- * http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html#PARAM-PASS
645
- */
646
-
647
- alias void * va_list;
648
-
649
- pragma (LDC_va_start)
650
- void va_start (T)(va_list ap, ref T);
651
-
652
- private pragma (LDC_va_arg)
653
- T va_arg_impl (T)(va_list ap);
654
-
655
- T va_arg (T)(ref va_list ap)
656
- {
657
- return va_arg_impl! T(ap);
658
- }
659
-
660
- void va_arg (T)(ref va_list ap, ref T parmn)
661
- {
662
- parmn = va_arg! T(ap);
663
- }
664
-
665
- void va_arg ()(ref va_list ap, TypeInfo ti, void * parmn)
666
- {
667
- // This works for all types because only the rules for non-floating,
668
- // non-vector types are used.
669
- auto tsize = ti.tsize();
670
- auto p = tsize < size_t .sizeof ? cast (void * )(cast (void * )ap + (size_t .sizeof - tsize)) : ap;
671
- ap = cast (va_list)(cast (void * )ap + ((tsize + size_t .sizeof - 1 ) & ~ (size_t .sizeof - 1 )));
672
- parmn[0 .. tsize] = p[0 .. tsize];
673
- }
674
-
675
- pragma (LDC_va_end)
676
- void va_end (va_list ap);
677
-
678
- pragma (LDC_va_copy)
679
- void va_copy (out va_list dest, va_list src);
680
- }
681
- }
682
596
else
683
597
{
684
598
static assert (false , " Unsupported platform" );
0 commit comments