Skip to content

Commit dc4e4e7

Browse files
committed
stdlib: add support for AAPCS64 variadics
The AAPCS64 ABI requires that `va_list` be defined as: typedef struct __va_list { void *__stack; /* next stack param */ void *__gr_top; /* end of GP reg save area */ void *__vr_top; /* end of FP/SIMD reg save area */ int __gr_offs; /* offset from __gr_top to next GP register arg */ int __vr_offs; /* offset from __vr_top to next FP register arg */ } va_list; This type does not decay and does not match pointer size. `__stack` points to the register save area. `__gr_top` points to the byte immediately following the GPR save area, which is rounded to a 16-byte boundary. `__vr_top` points to the byte immediately following the FPR save area, which is rounded to a 16-byte boundary. `__gr_offs` contains the `((8 - GRCount) * 8)`, `__vr_offs` contains `((8 - FPCount) * 16)`.
1 parent efa2208 commit dc4e4e7

File tree

3 files changed

+74
-4
lines changed

3 files changed

+74
-4
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ getSwiftStdlibType(const clang::TypedefNameDecl *D,
215215
return std::make_pair(Type(), "");
216216

217217
// Check other expected properties of the C type.
218-
switch(CTypeKind) {
218+
switch (CTypeKind) {
219219
case MappedCTypeKind::UnsignedInt:
220220
if (!ClangType->isUnsignedIntegerType())
221221
return std::make_pair(Type(), "");
@@ -273,8 +273,6 @@ getSwiftStdlibType(const clang::TypedefNameDecl *D,
273273
break;
274274

275275
case MappedCTypeKind::VaList:
276-
if (ClangTypeSize != ClangCtx.getTypeSize(ClangCtx.VoidPtrTy))
277-
return std::make_pair(Type(), "");
278276
break;
279277

280278
case MappedCTypeKind::ObjCBool:
@@ -334,6 +332,20 @@ getSwiftStdlibType(const clang::TypedefNameDecl *D,
334332
*IsError = true;
335333
return std::make_pair(Type(), "");
336334
}
335+
336+
if (CTypeKind == MappedCTypeKind::VaList) {
337+
const llvm::Triple &T = ClangCtx.getTargetInfo().getTriple();
338+
// Darwin AArch64 uses void * for the va_list type, while AAPCS64 uses a
339+
// custom type. Once the TODO below is addressed, this check should not be
340+
// needed.
341+
bool IsAAPCS64 = T.getArch() == llvm::Triple::AArch64 && !T.isOSDarwin();
342+
// TODO compare this against the size of the SwiftType rather than the
343+
// void * type.
344+
if (!IsAAPCS64 &&
345+
(ClangTypeSize != ClangCtx.getTypeSize(ClangCtx.VoidPtrTy)))
346+
return std::make_pair(Type(), "");
347+
}
348+
337349
return std::make_pair(SwiftType, SwiftTypeName);
338350
}
339351

stdlib/public/core/CTypes.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,30 @@ extension OpaquePointer : Equatable {
201201
}
202202

203203
/// The corresponding Swift type to `va_list` in imported C APIs.
204+
#if arch(arm64) && !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS))
205+
206+
// non-Darwin AAPCS64 ABI
207+
@_fixed_layout
208+
public struct CVaListPointer {
209+
@_versioned // FIXME(sil-serialize-all)
210+
internal var value: (__stack: UnsafeMutablePointer<Int>?,
211+
__gr_top: UnsafeMutablePointer<Int>?,
212+
__vr_top: UnsafeMutablePointer<Int>?,
213+
__gr_off: Int32,
214+
__vr_off: Int32)
215+
216+
@_inlineable // FIXME(sil-serialize-all)
217+
public // @testable
218+
init(__stack: UnsafeMutablePointer<Int>?,
219+
__gr_top: UnsafeMutablePointer<Int>?,
220+
__vr_top: UnsafeMutablePointer<Int>?,
221+
__gr_off: Int32,
222+
__vr_off: Int32) {
223+
value = (__stack, __gr_top, __vr_top, __gr_off, __vr_off)
224+
}
225+
}
226+
227+
#else
204228
@_fixed_layout
205229
public struct CVaListPointer {
206230
@_versioned // FIXME(sil-serialize-all)
@@ -220,6 +244,7 @@ extension CVaListPointer : CustomDebugStringConvertible {
220244
return value.debugDescription
221245
}
222246
}
247+
#endif
223248

224249
@_versioned
225250
@_inlineable

stdlib/public/core/VarArgs.swift

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,40 @@ extension Double : _CVarArgPassedAsDouble, _CVarArgAligned {
350350
}
351351
}
352352

353-
#if arch(x86_64)
353+
#if arch(arm64) && !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS))
354+
355+
@_fixed_layout // FIXME(sil-serialize-all)
356+
@_versioned // FIXME(sil-serialize-all)
357+
final internal class _VaListBuilder {
358+
@_versioned // FIXME(sil-serialize-all)
359+
internal var __stack: ContiguousArray<Int>
360+
361+
@_inlineable // FIXME(sil-serialize-all)
362+
@_versioned // FIXME(sil-serialize-all)
363+
internal init() {
364+
__stack = ContiguousArray(repeating: 0, count: 0)
365+
}
366+
367+
@_inlineable // FIXME(sil-serialize-all)
368+
@_versioned // FIXME(sil-serialize-all)
369+
deinit {}
370+
371+
@_inlineable // FIXME(sil-serialize-all)
372+
@_versioned // FIXME(sil-serialize-all)
373+
internal func append(_ arg: CVarArg) {
374+
}
375+
376+
@_inlineable // FIXME(sil-serialize-all)
377+
@_versioned // FIXME(sil-serialize-all)
378+
internal func va_list() -> CVaListPointer {
379+
let __gr_top = UnsafeMutablePointer<Int>(bitPattern: 0)
380+
let __vr_top = UnsafeMutablePointer<Int>(bitPattern: 0)
381+
return CVaListPointer(__stack: __stack._baseAddress, __gr_top: __gr_top,
382+
__vr_top: __vr_top, __gr_off: 0, __vr_off: 0)
383+
}
384+
}
385+
386+
#elseif arch(x86_64)
354387

355388
/// An object that can manage the lifetime of storage backing a
356389
/// `CVaListPointer`.

0 commit comments

Comments
 (0)