Skip to content

Commit f771e4c

Browse files
authored
Merge pull request #21237 from drodriguez/aapcs64-valist
[stdlib][SR-2239] Refactor AAPCS64 variable argument list support.
2 parents bc884d4 + 7cfaf9f commit f771e4c

File tree

3 files changed

+68
-149
lines changed

3 files changed

+68
-149
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,9 +322,19 @@ getSwiftStdlibType(const clang::TypedefNameDecl *D,
322322
break;
323323

324324
case MappedCTypeKind::VaList:
325-
if (ClangTypeSize != ClangCtx.getTypeSize(ClangCtx.VoidPtrTy)) {
326-
if (ClangCtx.getTargetInfo().getBuiltinVaListKind() !=
327-
clang::TargetInfo::AArch64ABIBuiltinVaList)
325+
switch (ClangCtx.getTargetInfo().getBuiltinVaListKind()) {
326+
case clang::TargetInfo::CharPtrBuiltinVaList:
327+
case clang::TargetInfo::VoidPtrBuiltinVaList:
328+
case clang::TargetInfo::PowerABIBuiltinVaList:
329+
case clang::TargetInfo::AAPCSABIBuiltinVaList:
330+
assert(ClangCtx.getTypeSize(ClangCtx.VoidPtrTy) == ClangTypeSize &&
331+
"expected va_list type to be sizeof(void *)");
332+
break;
333+
case clang::TargetInfo::AArch64ABIBuiltinVaList:
334+
break;
335+
case clang::TargetInfo::PNaClABIBuiltinVaList:
336+
case clang::TargetInfo::SystemZBuiltinVaList:
337+
case clang::TargetInfo::X86_64ABIBuiltinVaList:
328338
return std::make_pair(Type(), "");
329339
}
330340
break;

stdlib/public/core/CTypes.swift

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -219,15 +219,15 @@ extension UInt {
219219
}
220220

221221
/// A wrapper around a C `va_list` pointer.
222-
#if arch(arm64) && os(Linux)
222+
#if arch(arm64) && !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS) || os(Windows))
223223
@_fixed_layout
224224
public struct CVaListPointer {
225225
@usableFromInline // unsafe-performance
226-
internal var value: (__stack: UnsafeMutablePointer<Int>?,
227-
__gr_top: UnsafeMutablePointer<Int>?,
228-
__vr_top: UnsafeMutablePointer<Int>?,
229-
__gr_off: Int32,
230-
__vr_off: Int32)
226+
internal var _value: (__stack: UnsafeMutablePointer<Int>?,
227+
__gr_top: UnsafeMutablePointer<Int>?,
228+
__vr_top: UnsafeMutablePointer<Int>?,
229+
__gr_off: Int32,
230+
__vr_off: Int32)
231231

232232
@inlinable // unsafe-performance
233233
public // @testable
@@ -236,7 +236,17 @@ public struct CVaListPointer {
236236
__vr_top: UnsafeMutablePointer<Int>?,
237237
__gr_off: Int32,
238238
__vr_off: Int32) {
239-
value = (__stack, __gr_top, __vr_top, __gr_off, __vr_off)
239+
_value = (__stack, __gr_top, __vr_top, __gr_off, __vr_off)
240+
}
241+
}
242+
243+
extension CVaListPointer : CustomDebugStringConvertible {
244+
public var debugDescription: String {
245+
return "(\(_value.__stack.debugDescription), " +
246+
"\(_value.__gr_top.debugDescription), " +
247+
"\(_value.__vr_top.debugDescription), " +
248+
"\(_value.__gr_off), " +
249+
"\(_value.__vr_off))"
240250
}
241251
}
242252

stdlib/public/core/VarArgs.swift

Lines changed: 38 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ internal let _countGPRegisters = 16
9191
@usableFromInline
9292
internal let _registerSaveWords = _countGPRegisters
9393

94-
#elseif arch(arm64) && os(Linux)
94+
#elseif arch(arm64) && !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS) || os(Windows))
9595
// ARM Procedure Call Standard for aarch64. (IHI0055B)
9696
// The va_list type may refer to any parameter in a parameter list may be in one
9797
// of three memory locations depending on its type and position in the argument
@@ -408,7 +408,7 @@ extension Float80 : CVarArg, _CVarArgAligned {
408408
public var _cVarArgEncoding: [Int] {
409409
return _encodeBitsAsWords(self)
410410
}
411-
411+
412412
/// Returns the required alignment in bytes of
413413
/// the value returned by `_cVarArgEncoding`.
414414
@inlinable // FIXME(sil-serialize-all)
@@ -419,7 +419,7 @@ extension Float80 : CVarArg, _CVarArgAligned {
419419
}
420420
#endif
421421

422-
#if arch(x86_64) || arch(s390x)
422+
#if arch(x86_64) || arch(s390x) || (arch(arm64) && !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS) || os(Windows)))
423423

424424
/// An object that can manage the lifetime of storage backing a
425425
/// `CVaListPointer`.
@@ -429,6 +429,7 @@ extension Float80 : CVarArg, _CVarArgAligned {
429429
@_fixed_layout
430430
@usableFromInline // c-abi
431431
final internal class __VaListBuilder {
432+
#if arch(x86_64) || arch(s390x)
432433
@_fixed_layout // c-abi
433434
@usableFromInline
434435
internal struct Header {
@@ -445,15 +446,19 @@ final internal class __VaListBuilder {
445446
@usableFromInline // c-abi
446447
internal var reg_save_area: UnsafeMutablePointer<Int>?
447448
}
449+
#endif
448450

449451
@usableFromInline // c-abi
450452
internal var gpRegistersUsed = 0
451453
@usableFromInline // c-abi
452454
internal var fpRegistersUsed = 0
453455

456+
#if arch(x86_64) || arch(s390x)
454457
@usableFromInline // c-abi
455458
final // Property must be final since it is used by Builtin.addressof.
456459
internal var header = Header()
460+
#endif
461+
457462
@usableFromInline // c-abi
458463
internal var storage: ContiguousArray<Int>
459464

@@ -470,12 +475,16 @@ final internal class __VaListBuilder {
470475
internal func append(_ arg: CVarArg) {
471476
var encoded = arg._cVarArgEncoding
472477

473-
#if arch(x86_64)
478+
#if arch(x86_64) || arch(arm64)
474479
let isDouble = arg is _CVarArgPassedAsDouble
475480

476481
if isDouble && fpRegistersUsed < _countFPRegisters {
477-
var startIndex = _countGPRegisters
478-
+ (fpRegistersUsed * _fpRegisterWords)
482+
#if arch(arm64)
483+
var startIndex = fpRegistersUsed * _fpRegisterWords
484+
#else
485+
var startIndex = _countGPRegisters
486+
+ (fpRegistersUsed * _fpRegisterWords)
487+
#endif
479488
for w in encoded {
480489
storage[startIndex] = w
481490
startIndex += 1
@@ -485,7 +494,12 @@ final internal class __VaListBuilder {
485494
else if encoded.count == 1
486495
&& !isDouble
487496
&& gpRegistersUsed < _countGPRegisters {
488-
storage[gpRegistersUsed] = encoded[0]
497+
#if arch(arm64)
498+
let startIndex = ( _fpRegisterWords * _countFPRegisters) + gpRegistersUsed
499+
#else
500+
let startIndex = gpRegistersUsed
501+
#endif
502+
storage[startIndex] = encoded[0]
489503
gpRegistersUsed += 1
490504
}
491505
else {
@@ -510,139 +524,24 @@ final internal class __VaListBuilder {
510524

511525
@inlinable // c-abi
512526
internal func va_list() -> CVaListPointer {
513-
header.reg_save_area = storage._baseAddress
514-
header.overflow_arg_area
515-
= storage._baseAddress + _registerSaveWords
516-
return CVaListPointer(
517-
_fromUnsafeMutablePointer: UnsafeMutableRawPointer(
518-
Builtin.addressof(&self.header)))
519-
}
520-
}
521-
#elseif arch(arm64) && os(Linux)
522-
523-
// NOTE: older runtimes called this _VaListBuilder. The two must
524-
// coexist, so it was renamed. The old name must not be used in the new
525-
// runtime.
526-
@_fixed_layout // FIXME(sil-serialize-all)
527-
@usableFromInline // FIXME(sil-serialize-all)
528-
final internal class __VaListBuilder {
529-
@usableFromInline // FIXME(sil-serialize-all)
530-
internal init() {
531-
// Prepare the register save area.
532-
allocated = _registerSaveWords
533-
storage = allocStorage(wordCount: allocated)
534-
// Append stack arguments after register save area.
535-
count = allocated
536-
}
537-
538-
@usableFromInline // FIXME(sil-serialize-all)
539-
deinit {
540-
if let allocatedStorage = storage {
541-
deallocStorage(wordCount: allocated, storage: allocatedStorage)
542-
}
543-
}
544-
545-
@usableFromInline // FIXME(sil-serialize-all)
546-
internal func append(_ arg: CVarArg) {
547-
var encoded = arg._cVarArgEncoding
548-
549-
if arg is _CVarArgPassedAsDouble
550-
&& fpRegistersUsed < _countFPRegisters {
551-
var startIndex = (fpRegistersUsed * _fpRegisterWords)
552-
for w in encoded {
553-
storage[startIndex] = w
554-
startIndex += 1
555-
}
556-
fpRegistersUsed += 1
557-
} else if encoded.count == 1
558-
&& !(arg is _CVarArgPassedAsDouble)
559-
&& gpRegistersUsed < _countGPRegisters {
560-
var startIndex = ( _fpRegisterWords * _countFPRegisters) + gpRegistersUsed
561-
storage[startIndex] = encoded[0]
562-
gpRegistersUsed += 1
563-
} else {
564-
// Arguments in stack slot.
565-
appendWords(encoded)
566-
}
567-
}
568-
569-
@usableFromInline // FIXME(sil-serialize-all)
570-
internal func va_list() -> CVaListPointer {
571-
let vr_top = storage + (_fpRegisterWords * _countFPRegisters)
572-
let gr_top = vr_top + _countGPRegisters
573-
574-
return CVaListPointer(__stack: gr_top, __gr_top: gr_top,
575-
__vr_top: vr_top, __gr_off: -64, __vr_off: -128)
527+
#if arch(x86_64) || arch(s390x)
528+
header.reg_save_area = storage._baseAddress
529+
header.overflow_arg_area
530+
= storage._baseAddress + _registerSaveWords
531+
return CVaListPointer(
532+
_fromUnsafeMutablePointer: UnsafeMutableRawPointer(
533+
Builtin.addressof(&self.header)))
534+
#elseif arch(arm64)
535+
let vr_top = storage._baseAddress + (_fpRegisterWords * _countFPRegisters)
536+
let gr_top = vr_top + _countGPRegisters
537+
538+
return CVaListPointer(__stack: gr_top,
539+
__gr_top: gr_top,
540+
__vr_top: vr_top,
541+
__gr_off: -64,
542+
__vr_off: -128)
543+
#endif
576544
}
577-
578-
@usableFromInline // FIXME(sil-serialize-all)
579-
internal func appendWords(_ words: [Int]) {
580-
let newCount = count + words.count
581-
if newCount > allocated {
582-
let oldAllocated = allocated
583-
let oldStorage = storage
584-
let oldCount = count
585-
586-
allocated = max(newCount, allocated * 2)
587-
let newStorage = allocStorage(wordCount: allocated)
588-
storage = newStorage
589-
// Count is updated below.
590-
if let allocatedOldStorage = oldStorage {
591-
newStorage.moveInitialize(from: allocatedOldStorage, count: oldCount)
592-
deallocStorage(wordCount: oldAllocated, storage: allocatedOldStorage)
593-
}
594-
}
595-
596-
let allocatedStorage = storage!
597-
for word in words {
598-
allocatedStorage[count] = word
599-
count += 1
600-
}
601-
}
602-
603-
@usableFromInline // FIXME(sil-serialize-all)
604-
internal func rawSizeAndAlignment(
605-
_ wordCount: Int
606-
) -> (Builtin.Word, Builtin.Word) {
607-
return ((wordCount * MemoryLayout<Int>.stride)._builtinWordValue,
608-
requiredAlignmentInBytes._builtinWordValue)
609-
}
610-
611-
@usableFromInline // FIXME(sil-serialize-all)
612-
internal func allocStorage(wordCount: Int) -> UnsafeMutablePointer<Int> {
613-
let (rawSize, rawAlignment) = rawSizeAndAlignment(wordCount)
614-
let rawStorage = Builtin.allocRaw(rawSize, rawAlignment)
615-
return UnsafeMutablePointer<Int>(rawStorage)
616-
}
617-
618-
@usableFromInline // FIXME(sil-serialize-all)
619-
internal func deallocStorage(
620-
wordCount: Int, storage: UnsafeMutablePointer<Int>
621-
) {
622-
let (rawSize, rawAlignment) = rawSizeAndAlignment(wordCount)
623-
Builtin.deallocRaw(storage._rawValue, rawSize, rawAlignment)
624-
}
625-
626-
@usableFromInline // FIXME(sil-serialize-all)
627-
internal let requiredAlignmentInBytes = MemoryLayout<Double>.alignment
628-
629-
@usableFromInline // FIXME(sil-serialize-all)
630-
internal var count = 0
631-
632-
@usableFromInline // FIXME(sil-serialize-all)
633-
internal var allocated = 0
634-
635-
@usableFromInline // FIXME(sil-serialize-all)
636-
internal var storage: UnsafeMutablePointer<Int>!
637-
638-
@usableFromInline // FIXME(sil-serialize-all)
639-
internal var gpRegistersUsed = 0
640-
641-
@usableFromInline // FIXME(sil-serialize-all)
642-
internal var fpRegistersUsed = 0
643-
644-
@usableFromInline // FIXME(sil-serialize-all)
645-
internal var overflowWordsUsed = 0
646545
}
647546

648547
#else

0 commit comments

Comments
 (0)