mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[wasm] Add support for __builtin_va_list type mapping (#84029)
Cover all va_list family of types just aliased by __builtin_va_list, including __isoc_va_list from wasi-libc. This enables proper C interop for variable argument functions on WASI targets. Close https://github.com/swiftlang/swift/issues/72398
This commit is contained in:
@@ -129,6 +129,9 @@ MAP_STDLIB_TYPE("u_int64_t", UnsignedInt, 64, "UInt64", false, DoNothing)
|
|||||||
MAP_STDLIB_TYPE("va_list", VaList, 0, "CVaListPointer", false, DoNothing)
|
MAP_STDLIB_TYPE("va_list", VaList, 0, "CVaListPointer", false, DoNothing)
|
||||||
MAP_STDLIB_TYPE("__gnuc_va_list", VaList, 0, "CVaListPointer", false, DoNothing)
|
MAP_STDLIB_TYPE("__gnuc_va_list", VaList, 0, "CVaListPointer", false, DoNothing)
|
||||||
MAP_STDLIB_TYPE("__va_list", VaList, 0, "CVaListPointer", false, DoNothing)
|
MAP_STDLIB_TYPE("__va_list", VaList, 0, "CVaListPointer", false, DoNothing)
|
||||||
|
// Cover all va_list family of types just aliased by __builtin_va_list, including
|
||||||
|
// __isoc_va_list from wasi-libc.
|
||||||
|
MAP_STDLIB_TYPE("__builtin_va_list", VaList, 0, "CVaListPointer", false, DoNothing)
|
||||||
|
|
||||||
// libkern/OSTypes.h types.
|
// libkern/OSTypes.h types.
|
||||||
MAP_STDLIB_TYPE("UInt", UnsignedInt, 32, "CUnsignedInt", false, DoNothing)
|
MAP_STDLIB_TYPE("UInt", UnsignedInt, 32, "CUnsignedInt", false, DoNothing)
|
||||||
|
|||||||
7
test/ClangImporter/Inputs/custom-modules/CVarArgs.h
Normal file
7
test/ClangImporter/Inputs/custom-modules/CVarArgs.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#include <stdarg.h>
|
||||||
|
extern void takeVaList(va_list args);
|
||||||
|
|
||||||
|
extern void takeVaList2(__builtin_va_list args);
|
||||||
|
|
||||||
|
typedef __builtin_va_list my_builtin_va_list_alias;
|
||||||
|
extern void takeVaList3(my_builtin_va_list_alias args);
|
||||||
@@ -283,3 +283,8 @@ module Aliases {
|
|||||||
module RetroactiveVersioning {
|
module RetroactiveVersioning {
|
||||||
header "versioning.h"
|
header "versioning.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module CVarArgs {
|
||||||
|
header "CVarArgs.h"
|
||||||
|
export *
|
||||||
|
}
|
||||||
|
|||||||
18
test/ClangImporter/ctypes_valist_wasm.swift
Normal file
18
test/ClangImporter/ctypes_valist_wasm.swift
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// RUN: %swift-frontend -target wasm32-unknown-wasip1 -parse-stdlib -module-name Swift -I %S/Inputs/custom-modules -typecheck %s
|
||||||
|
|
||||||
|
// REQUIRES: CODEGENERATOR=WebAssembly
|
||||||
|
|
||||||
|
import CVarArgs
|
||||||
|
|
||||||
|
/// ===== Minimal stdlib definitions =====
|
||||||
|
typealias Void = ()
|
||||||
|
struct CVaListPointer {}
|
||||||
|
// Optional definition is required for isOptional check in ClangImporter
|
||||||
|
enum Optional<T> {}
|
||||||
|
/// ======================================
|
||||||
|
|
||||||
|
func testVaList() {
|
||||||
|
let _: (CVaListPointer) -> Void = CVarArgs.takeVaList
|
||||||
|
let _: (CVaListPointer) -> Void = CVarArgs.takeVaList2
|
||||||
|
let _: (CVaListPointer) -> Void = CVarArgs.takeVaList3
|
||||||
|
}
|
||||||
@@ -193,6 +193,25 @@ func test_varArgs7() {
|
|||||||
}
|
}
|
||||||
test_varArgs7()
|
test_varArgs7()
|
||||||
|
|
||||||
|
func test_varArgs8() {
|
||||||
|
// Check with vsnprintf as well just in case to make sure it works with C APIs
|
||||||
|
// imported from actual libc headers. Why checks with vprintf above are not enough?
|
||||||
|
// ClangImporter respects the vprintf interface re-defined in LibcShims.h but it could
|
||||||
|
// be slightly different than the one in platform libc on some platforms, including WASI.
|
||||||
|
// (e.g. wasi-libc defines `int vprintf(const char *__restrict, __isoc_va_list);` where
|
||||||
|
// `__isoc_va_list` is `typedef __builtin_va_list __isoc_va_list;`, but LibcShims.h aliases
|
||||||
|
// __builtin_va_list as `va_list`.)
|
||||||
|
// https://github.com/swiftlang/swift/issues/72398
|
||||||
|
let string = withUnsafeTemporaryAllocation(of: CChar.self, capacity: 512) { buffer in
|
||||||
|
withVaList([CInt(123)]) { args in
|
||||||
|
_ = vsnprintf(buffer.baseAddress!, buffer.count, "%d", args)
|
||||||
|
}
|
||||||
|
return String(cString: buffer.baseAddress!)
|
||||||
|
}
|
||||||
|
print(string)
|
||||||
|
// CHECK: 123
|
||||||
|
}
|
||||||
|
test_varArgs8()
|
||||||
|
|
||||||
// CHECK: done.
|
// CHECK: done.
|
||||||
my_printf("done.")
|
my_printf("done.")
|
||||||
|
|||||||
Reference in New Issue
Block a user