Skip to content

Commit

Permalink
Merge pull request swiftlang#20862 from futurejones/master-aarch64-Va…
Browse files Browse the repository at this point in the history
…rArgs

[stdlib][SR-2239]: add support for AArch64 variadics
  • Loading branch information
tkremenek authored Nov 29, 2018
2 parents fb8b9e1 + 4a03b3c commit deb0f1f
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 2 deletions.
7 changes: 5 additions & 2 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,11 @@ getSwiftStdlibType(const clang::TypedefNameDecl *D,
break;

case MappedCTypeKind::VaList:
if (ClangTypeSize != ClangCtx.getTypeSize(ClangCtx.VoidPtrTy))
return std::make_pair(Type(), "");
if (ClangTypeSize != ClangCtx.getTypeSize(ClangCtx.VoidPtrTy)) {
if (ClangCtx.getTargetInfo().getBuiltinVaListKind() !=
clang::TargetInfo::AArch64ABIBuiltinVaList)
return std::make_pair(Type(), "");
}
break;

case MappedCTypeKind::ObjCBool:
Expand Down
25 changes: 25 additions & 0 deletions stdlib/public/core/CTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,29 @@ extension UInt {
}

/// A wrapper around a C `va_list` pointer.
#if arch(arm64) && os(Linux)
@_fixed_layout
public struct CVaListPointer {
@usableFromInline // unsafe-performance
internal var value: (__stack: UnsafeMutablePointer<Int>?,
__gr_top: UnsafeMutablePointer<Int>?,
__vr_top: UnsafeMutablePointer<Int>?,
__gr_off: Int32,
__vr_off: Int32)

@inlinable // unsafe-performance
public // @testable
init(__stack: UnsafeMutablePointer<Int>?,
__gr_top: UnsafeMutablePointer<Int>?,
__vr_top: UnsafeMutablePointer<Int>?,
__gr_off: Int32,
__vr_off: Int32) {
value = (__stack, __gr_top, __vr_top, __gr_off, __vr_off)
}
}

#else

@_fixed_layout
public struct CVaListPointer {
@usableFromInline // unsafe-performance
Expand All @@ -238,6 +261,8 @@ extension CVaListPointer : CustomDebugStringConvertible {
}
}

#endif

@inlinable
internal func _memcpy(
dest destination: UnsafeMutableRawPointer,
Expand Down
140 changes: 140 additions & 0 deletions stdlib/public/core/VarArgs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,23 @@ internal let _registerSaveWords = _countGPRegisters + _countFPRegisters * _fpReg
internal let _countGPRegisters = 16
@usableFromInline
internal let _registerSaveWords = _countGPRegisters

#elseif arch(arm64) && os(Linux)
// ARM Procedure Call Standard for aarch64. (IHI0055B)
// The va_list type may refer to any parameter in a parameter list may be in one
// of three memory locations depending on its type and position in the argument
// list :
// 1. GP register save area x0 - x7
// 2. 128-bit FP/SIMD register save area q0 - q7
// 3. Stack argument area
@usableFromInline
internal let _countGPRegisters = 8
@usableFromInline
internal let _countFPRegisters = 8
@usableFromInline
internal let _fpRegisterWords = 16 / MemoryLayout<Int>.size
@usableFromInline
internal let _registerSaveWords = _countGPRegisters + (_countFPRegisters * _fpRegisterWords)
#endif

#if arch(s390x)
Expand Down Expand Up @@ -498,6 +515,129 @@ final internal class _VaListBuilder {
Builtin.addressof(&self.header)))
}
}
#elseif arch(arm64) && os(Linux)

@_fixed_layout // FIXME(sil-serialize-all)
@usableFromInline // FIXME(sil-serialize-all)
final internal class _VaListBuilder {
@usableFromInline // FIXME(sil-serialize-all)
internal init() {
// Prepare the register save area.
allocated = _registerSaveWords
storage = allocStorage(wordCount: allocated)
// Append stack arguments after register save area.
count = allocated
}

@usableFromInline // FIXME(sil-serialize-all)
deinit {
if let allocatedStorage = storage {
deallocStorage(wordCount: allocated, storage: allocatedStorage)
}
}

@usableFromInline // FIXME(sil-serialize-all)
internal func append(_ arg: CVarArg) {
var encoded = arg._cVarArgEncoding

if arg is _CVarArgPassedAsDouble
&& fpRegistersUsed < _countFPRegisters {
var startIndex = (fpRegistersUsed * _fpRegisterWords)
for w in encoded {
storage[startIndex] = w
startIndex += 1
}
fpRegistersUsed += 1
} else if encoded.count == 1
&& !(arg is _CVarArgPassedAsDouble)
&& gpRegistersUsed < _countGPRegisters {
var startIndex = ( _fpRegisterWords * _countFPRegisters) + gpRegistersUsed
storage[startIndex] = encoded[0]
gpRegistersUsed += 1
} else {
// Arguments in stack slot.
appendWords(encoded)
}
}

@usableFromInline // FIXME(sil-serialize-all)
internal func va_list() -> CVaListPointer {
let vr_top = storage + (_fpRegisterWords * _countFPRegisters)
let gr_top = vr_top + _countGPRegisters

return CVaListPointer(__stack: gr_top, __gr_top: gr_top,
__vr_top: vr_top, __gr_off: -64, __vr_off: -128)
}

@usableFromInline // FIXME(sil-serialize-all)
internal func appendWords(_ words: [Int]) {
let newCount = count + words.count
if newCount > allocated {
let oldAllocated = allocated
let oldStorage = storage
let oldCount = count

allocated = max(newCount, allocated * 2)
let newStorage = allocStorage(wordCount: allocated)
storage = newStorage
// Count is updated below.
if let allocatedOldStorage = oldStorage {
newStorage.moveInitialize(from: allocatedOldStorage, count: oldCount)
deallocStorage(wordCount: oldAllocated, storage: allocatedOldStorage)
}
}

let allocatedStorage = storage!
for word in words {
allocatedStorage[count] = word
count += 1
}
}

@usableFromInline // FIXME(sil-serialize-all)
internal func rawSizeAndAlignment(
_ wordCount: Int
) -> (Builtin.Word, Builtin.Word) {
return ((wordCount * MemoryLayout<Int>.stride)._builtinWordValue,
requiredAlignmentInBytes._builtinWordValue)
}

@usableFromInline // FIXME(sil-serialize-all)
internal func allocStorage(wordCount: Int) -> UnsafeMutablePointer<Int> {
let (rawSize, rawAlignment) = rawSizeAndAlignment(wordCount)
let rawStorage = Builtin.allocRaw(rawSize, rawAlignment)
return UnsafeMutablePointer<Int>(rawStorage)
}

@usableFromInline // FIXME(sil-serialize-all)
internal func deallocStorage(
wordCount: Int, storage: UnsafeMutablePointer<Int>
) {
let (rawSize, rawAlignment) = rawSizeAndAlignment(wordCount)
Builtin.deallocRaw(storage._rawValue, rawSize, rawAlignment)
}

@usableFromInline // FIXME(sil-serialize-all)
internal let requiredAlignmentInBytes = MemoryLayout<Double>.alignment

@usableFromInline // FIXME(sil-serialize-all)
internal var count = 0

@usableFromInline // FIXME(sil-serialize-all)
internal var allocated = 0

@usableFromInline // FIXME(sil-serialize-all)
internal var storage: UnsafeMutablePointer<Int>!

@usableFromInline // FIXME(sil-serialize-all)
internal var gpRegistersUsed = 0

@usableFromInline // FIXME(sil-serialize-all)
internal var fpRegistersUsed = 0

@usableFromInline // FIXME(sil-serialize-all)
internal var overflowWordsUsed = 0
}

#else

Expand Down

0 comments on commit deb0f1f

Please sign in to comment.