@@ -90,6 +90,23 @@ internal let _registerSaveWords = _countGPRegisters + _countSSERegisters * _sseR
90
90
internal let _countGPRegisters = 16
91
91
@usableFromInline
92
92
internal let _registerSaveWords = _countGPRegisters
93
+
94
+ #elseif arch(arm64) && os(Linux)
95
+ // ARM Procedure Call Standard for aarch64. (IHI0055B)
96
+ // The va_list type may refer to any parameter in a parameter list may be in one
97
+ // of three memory locations depending on its type and position in the argument
98
+ // list :
99
+ // 1. GP register save area x0 - x7
100
+ // 2. 128-bit FP/SIMD register save area q0 - q7
101
+ // 3. Stack argument area
102
+ @_versioned
103
+ internal let _countGPRegisters = 8
104
+ @_versioned
105
+ internal let _countFPRegisters = 8
106
+ @_versioned
107
+ internal let _fpRegisterWords = 16 / MemoryLayout< Int> . size
108
+ @_versioned
109
+ internal let _registerSaveWords = _countGPRegisters + ( _countFPRegisters * _fpRegisterWords)
93
110
#endif
94
111
95
112
#if arch(s390x)
@@ -476,6 +493,137 @@ final internal class _VaListBuilder {
476
493
internal var storage : ContiguousArray < Int >
477
494
}
478
495
496
+ #elseif arch(arm64) && os(Linux)
497
+
498
+ @_fixed_layout // FIXME(sil-serialize-all)
499
+ @_versioned // FIXME(sil-serialize-all)
500
+ final internal class _VaListBuilder {
501
+ @_inlineable // FIXME(sil-serialize-all)
502
+ @_versioned // FIXME(sil-serialize-all)
503
+ internal init ( ) {
504
+ // Prepare the register save area.
505
+ allocated = _registerSaveWords
506
+ storage = allocStorage ( wordCount: allocated)
507
+ // Append stack arguments after register save area.
508
+ count = allocated
509
+ }
510
+
511
+ @_inlineable // FIXME(sil-serialize-all)
512
+ @_versioned // FIXME(sil-serialize-all)
513
+ deinit {
514
+ if let allocatedStorage = storage {
515
+ deallocStorage ( wordCount: allocated, storage: allocatedStorage)
516
+ }
517
+ }
518
+
519
+ @_inlineable // FIXME(sil-serialize-all)
520
+ @_versioned // FIXME(sil-serialize-all)
521
+ internal func append( _ arg: CVarArg ) {
522
+ var encoded = arg. _cVarArgEncoding
523
+
524
+ if arg is _CVarArgPassedAsDouble
525
+ && fpRegistersUsed < _countFPRegisters {
526
+ var startIndex = ( fpRegistersUsed * _fpRegisterWords)
527
+ for w in encoded {
528
+ storage [ startIndex] = w
529
+ startIndex += 1
530
+ }
531
+ fpRegistersUsed += 1
532
+ } else if encoded. count == 1
533
+ && !( arg is _CVarArgPassedAsDouble )
534
+ && gpRegistersUsed < _countGPRegisters {
535
+ var startIndex = ( _fpRegisterWords * _countFPRegisters) + gpRegistersUsed
536
+ storage [ startIndex] = encoded [ 0 ]
537
+ gpRegistersUsed += 1
538
+ } else {
539
+ // Arguments in stack slot.
540
+ appendWords ( encoded)
541
+ }
542
+ }
543
+
544
+ @_inlineable // FIXME(sil-serialize-all)
545
+ @_versioned // FIXME(sil-serialize-all)
546
+ internal func va_list( ) -> CVaListPointer {
547
+ let vr_top = storage + ( _fpRegisterWords * _countFPRegisters)
548
+ let gr_top = vr_top + _countGPRegisters
549
+
550
+ return CVaListPointer ( __stack: gr_top, __gr_top: gr_top,
551
+ __vr_top: vr_top, __gr_off: - 64 , __vr_off: - 128 )
552
+ }
553
+
554
+ @_inlineable // FIXME(sil-serialize-all)
555
+ @_versioned // FIXME(sil-serialize-all)
556
+ internal func appendWords( _ words: [ Int ] ) {
557
+ let newCount = count + words. count
558
+ if newCount > allocated {
559
+ let oldAllocated = allocated
560
+ let oldStorage = storage
561
+ let oldCount = count
562
+
563
+ allocated = max ( newCount, allocated * 2 )
564
+ let newStorage = allocStorage ( wordCount: allocated)
565
+ storage = newStorage
566
+ // Count is updated below.
567
+ if let allocatedOldStorage = oldStorage {
568
+ newStorage. moveInitialize ( from: allocatedOldStorage, count: oldCount)
569
+ deallocStorage ( wordCount: oldAllocated, storage: allocatedOldStorage)
570
+ }
571
+ }
572
+
573
+ let allocatedStorage = storage!
574
+ for word in words {
575
+ allocatedStorage [ count] = word
576
+ count += 1
577
+ }
578
+ }
579
+
580
+ @_inlineable // FIXME(sil-serialize-all)
581
+ @_versioned // FIXME(sil-serialize-all)
582
+ internal func rawSizeAndAlignment(
583
+ _ wordCount: Int
584
+ ) -> ( Builtin . Word , Builtin . Word ) {
585
+ return ( ( wordCount * MemoryLayout < Int > . stride) . _builtinWordValue,
586
+ requiredAlignmentInBytes. _builtinWordValue)
587
+ }
588
+
589
+ @_inlineable // FIXME(sil-serialize-all)
590
+ @_versioned // FIXME(sil-serialize-all)
591
+ internal func allocStorage( wordCount: Int ) -> UnsafeMutablePointer < Int > {
592
+ let ( rawSize, rawAlignment) = rawSizeAndAlignment ( wordCount)
593
+ let rawStorage = Builtin . allocRaw ( rawSize, rawAlignment)
594
+ return UnsafeMutablePointer < Int > ( rawStorage)
595
+ }
596
+
597
+ @_versioned // FIXME(sil-serialize-all)
598
+ internal func deallocStorage(
599
+ wordCount: Int , storage: UnsafeMutablePointer < Int >
600
+ ) {
601
+ let ( rawSize, rawAlignment) = rawSizeAndAlignment ( wordCount)
602
+ Builtin . deallocRaw ( storage. _rawValue, rawSize, rawAlignment)
603
+ }
604
+
605
+ @_versioned // FIXME(sil-serialize-all)
606
+ internal let requiredAlignmentInBytes = MemoryLayout< Double> . alignment
607
+
608
+ @_versioned // FIXME(sil-serialize-all)
609
+ internal var count = 0
610
+
611
+ @_versioned // FIXME(sil-serialize-all)
612
+ internal var allocated = 0
613
+
614
+ @_versioned // FIXME(sil-serialize-all)
615
+ internal var storage : UnsafeMutablePointer < Int > !
616
+
617
+ @_versioned // FIXME(sil-serialize-all)
618
+ internal var gpRegistersUsed = 0
619
+
620
+ @_versioned // FIXME(sil-serialize-all)
621
+ internal var fpRegistersUsed = 0
622
+
623
+ @_versioned // FIXME(sil-serialize-all)
624
+ internal var overflowWordsUsed = 0
625
+ }
626
+
479
627
#else
480
628
481
629
/// An object that can manage the lifetime of storage backing a
0 commit comments