diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6778c1cb..f88eacb8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -126,7 +126,7 @@ jobs: wasi-swift-sdk-checksum: "b64dfad9e1c9ccdf06f35cf9b1a00317e000df0c0de0b3eb9f49d6db0fcba4d9" test-args: "-Xswiftc -DWASMKIT_CI_TOOLCHAIN_NIGHTLY" - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 name: "build-linux (${{ matrix.swift }})" steps: @@ -240,7 +240,7 @@ jobs: run: swift test build-cmake: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 container: image: swift:6.2-noble steps: @@ -254,3 +254,17 @@ jobs: - run: cmake -G Ninja -B ./build - run: cmake --build ./build - run: ./build/bin/wasmkit-cli --version + + build-wasi: + runs-on: ubuntu-24.04 + container: + image: swift:6.2-noble + steps: + - uses: actions/checkout@v4 + - name: Install jq + run: apt-get update && apt-get install -y jq + - name: Install Swift SDK + run: swift sdk install https://download.swift.org/swift-6.2-release/wasm/swift-6.2-RELEASE/swift-6.2-RELEASE_wasm.artifactbundle.tar.gz --checksum fe4e8648309fce86ea522e9e0d1dc48e82df6ba6e5743dbf0c53db8429fb5224 + - name: Build with the Swift SDK + run: swift build --swift-sdk "$(swiftc -print-target-info | jq -r '.swiftCompilerTag')_wasm" + diff --git a/Package.swift b/Package.swift index cc6f66cf..aa82983a 100644 --- a/Package.swift +++ b/Package.swift @@ -89,7 +89,8 @@ let package = Package( .target( name: "SystemExtras", dependencies: [ - .product(name: "SystemPackage", package: "swift-system") + .product(name: "SystemPackage", package: "swift-system"), + .target(name: "CSystemExtras", condition: .when(platforms: [.wasi])), ], exclude: ["CMakeLists.txt"], swiftSettings: [ @@ -97,6 +98,8 @@ let package = Package( ] ), + .target(name: "CSystemExtras"), + .executableTarget( name: "WITTool", dependencies: [ @@ -120,8 +123,8 @@ let package = Package( if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil { package.dependencies += [ - .package(url: "https://github.com/apple/swift-argument-parser", from: "1.2.2"), - .package(url: "https://github.com/apple/swift-system", .upToNextMajor(from: "1.3.0")), + .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.1"), + .package(url: "https://github.com/apple/swift-system", from: "1.5.0"), ] } else { package.dependencies += [ diff --git a/Sources/CLI/Commands/Run.swift b/Sources/CLI/Commands/Run.swift index e7461fae..7c525617 100644 --- a/Sources/CLI/Commands/Run.swift +++ b/Sources/CLI/Commands/Run.swift @@ -59,12 +59,16 @@ struct Run: ParsableCommand { var directories: [String] = [] enum ThreadingModel: String, ExpressibleByArgument, CaseIterable { - case direct + #if !os(WASI) + case direct + #endif case token func resolve() -> EngineConfiguration.ThreadingModel { switch self { - case .direct: return .direct + #if !os(WASI) + case .direct: return .direct + #endif case .token: return .token } } diff --git a/Sources/CSystemExtras/CSystemExtras.c b/Sources/CSystemExtras/CSystemExtras.c new file mode 100644 index 00000000..e69de29b diff --git a/Sources/CSystemExtras/include/clock.h b/Sources/CSystemExtras/include/clock.h new file mode 100644 index 00000000..ddcdc6fa --- /dev/null +++ b/Sources/CSystemExtras/include/clock.h @@ -0,0 +1,5 @@ +#include + +inline static clockid_t csystemextras_monotonic_clockid() { + return CLOCK_MONOTONIC; +} diff --git a/Sources/SystemExtras/Clock.swift b/Sources/SystemExtras/Clock.swift index b0282d20..3a040258 100644 --- a/Sources/SystemExtras/Clock.swift +++ b/Sources/SystemExtras/Clock.swift @@ -12,6 +12,9 @@ import Android #elseif os(Windows) import CSystem import ucrt +#elseif os(WASI) +import CSystemExtras +import WASILibc #else #error("Unsupported Platform") #endif @@ -41,12 +44,17 @@ extension Clock { public static var rawMonotonic: Clock { Clock(rawValue: _CLOCK_MONOTONIC_RAW) } #endif - #if SYSTEM_PACKAGE_DARWIN || os(Linux) || os(Android) || os(OpenBSD) || os(FreeBSD) || os(WASI) + #if SYSTEM_PACKAGE_DARWIN || os(Linux) || os(Android) || os(OpenBSD) || os(FreeBSD) @_alwaysEmitIntoClient public static var monotonic: Clock { Clock(rawValue: _CLOCK_MONOTONIC) } #endif - #if os(OpenBSD) || os(FreeBSD) || os(WASI) + #if os(WASI) + @_alwaysEmitIntoClient + public static var monotonic: Clock { Clock(rawValue: csystemextras_monotonic_clockid()) } + #endif + + #if os(OpenBSD) || os(FreeBSD) @_alwaysEmitIntoClient public static var uptime: Clock { Clock(rawValue: _CLOCK_UPTIME) } #endif @@ -92,10 +100,10 @@ extension Clock { public var rawValue: CInterop.TimeSpec @_alwaysEmitIntoClient - public var seconds: Int { rawValue.tv_sec } + public var seconds: Int64 { .init(rawValue.tv_sec) } @_alwaysEmitIntoClient - public var nanoseconds: Int { rawValue.tv_nsec } + public var nanoseconds: Int64 { .init(rawValue.tv_nsec) } @_alwaysEmitIntoClient public init(rawValue: CInterop.TimeSpec) { @@ -104,17 +112,25 @@ extension Clock { @_alwaysEmitIntoClient public init(seconds: Int, nanoseconds: Int) { - self.init(rawValue: CInterop.TimeSpec(tv_sec: seconds, tv_nsec: nanoseconds)) + self.init(rawValue: CInterop.TimeSpec(tv_sec: .init(seconds), tv_nsec: nanoseconds)) } @_alwaysEmitIntoClient public static var now: TimeSpec { +#if os(WASI) + return TimeSpec(rawValue: CInterop.TimeSpec(tv_sec: 0, tv_nsec: Int(UTIME_NOW))) +#else return TimeSpec(rawValue: CInterop.TimeSpec(tv_sec: 0, tv_nsec: Int(_UTIME_NOW))) +#endif } @_alwaysEmitIntoClient public static var omit: TimeSpec { +#if os(WASI) + return TimeSpec(rawValue: CInterop.TimeSpec(tv_sec: 0, tv_nsec: Int(UTIME_OMIT))) +#else return TimeSpec(rawValue: CInterop.TimeSpec(tv_sec: 0, tv_nsec: Int(_UTIME_OMIT))) +#endif } } } diff --git a/Sources/SystemExtras/Constants.swift b/Sources/SystemExtras/Constants.swift index 1c48c0ed..29a81d6a 100644 --- a/Sources/SystemExtras/Constants.swift +++ b/Sources/SystemExtras/Constants.swift @@ -12,6 +12,8 @@ import Android #elseif os(Windows) import CSystem import ucrt +#elseif os(WASI) +import WASILibc #else #error("Unsupported Platform") #endif @@ -43,7 +45,7 @@ internal var _AT_NO_AUTOMOUNT: CInt { AT_NO_AUTOMOUNT } #endif */ -#if !os(Windows) +#if !os(Windows) && !os(WASI) @_alwaysEmitIntoClient internal var _F_GETFL: CInt { F_GETFL } @_alwaysEmitIntoClient @@ -61,7 +63,7 @@ internal var _O_SYNC: CInt { O_SYNC } internal var _O_RSYNC: CInt { O_RSYNC } #endif -#if !os(Windows) +#if !os(Windows) && !os(WASI) @_alwaysEmitIntoClient internal var _UTIME_NOW: CInt { #if os(Linux) || os(Android) @@ -132,16 +134,15 @@ internal var _CLOCK_BOOTTIME: CInterop.ClockId { CLOCK_BOOTTIME } @_alwaysEmitIntoClient internal var _CLOCK_MONOTONIC_RAW: CInterop.ClockId { CLOCK_MONOTONIC_RAW } #endif -#if SYSTEM_PACKAGE_DARWIN || os(Linux) || os(Android) || os(OpenBSD) || os(FreeBSD) || os(WASI) +#if SYSTEM_PACKAGE_DARWIN || os(Linux) || os(Android) || os(OpenBSD) || os(FreeBSD) @_alwaysEmitIntoClient internal var _CLOCK_MONOTONIC: CInterop.ClockId { CLOCK_MONOTONIC } #endif - #if SYSTEM_PACKAGE_DARWIN @_alwaysEmitIntoClient internal var _CLOCK_UPTIME_RAW: CInterop.ClockId { CLOCK_UPTIME_RAW } #endif -#if os(OpenBSD) || os(FreeBSD) || os(WASI) +#if os(OpenBSD) || os(FreeBSD) @_alwaysEmitIntoClient internal var _CLOCK_UPTIME: CInterop.ClockId { CLOCK_UPTIME } #endif diff --git a/Sources/SystemExtras/FileAtOperations.swift b/Sources/SystemExtras/FileAtOperations.swift index 5f8f3838..7baf2847 100644 --- a/Sources/SystemExtras/FileAtOperations.swift +++ b/Sources/SystemExtras/FileAtOperations.swift @@ -12,6 +12,8 @@ import Android #elseif os(Windows) import ucrt import WinSDK +#elseif os(WASI) +import WASILibc #else #error("Unsupported Platform") #endif diff --git a/Sources/SystemExtras/FileOperations.swift b/Sources/SystemExtras/FileOperations.swift index fc61b1d8..7b6f1902 100644 --- a/Sources/SystemExtras/FileOperations.swift +++ b/Sources/SystemExtras/FileOperations.swift @@ -12,6 +12,8 @@ import Android #elseif os(Windows) import ucrt import WinSDK +#elseif os(WASI) +import WASILibc #else #error("Unsupported Platform") #endif @@ -344,6 +346,8 @@ extension FileDescriptor { #if os(Windows) // FIXME: Need to query by `NtQueryInformationFile`? return .success(OpenOptions(rawValue: 0)) + #elseif os(WASI) + return .failure(Errno.notSupported) #else valueOrErrno(retryOnInterrupt: false) { system_fcntl(self.rawValue, _F_GETFL) @@ -511,15 +515,31 @@ extension FileDescriptor { @_alwaysEmitIntoClient public var name: String { +#if os(WASI) + // ClangImporter can't handle `char d_name[]`, but it's right after `unsigned char d_type`. + withUnsafePointer(to: &rawValue.pointee.d_type) { dType in + let dName = dType + 1 + return dName.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: dName)) { + // String initializer copies the given buffer contents, so it's safe. + return String(cString: $0) + } + } +#else withUnsafePointer(to: &rawValue.pointee.d_name) { dName in dName.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: dName)) { // String initializer copies the given buffer contents, so it's safe. return String(cString: $0) } } + #endif } public var fileType: FileType { +#if os(WASI) + // https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#-filetype-variant + // https://github.com/WebAssembly/wasi-libc/blob/6b45da5b05bc0edda355a6de46101d4b21631985/libc-bottom-half/headers/public/wasi/api.h#L780C9-L780C32 + FileType(rawValue: .init(rawValue.pointee.d_type)) +#else switch CInt(rawValue.pointee.d_type) { case _DT_REG: return .file case _DT_BLK: return .blockDevice @@ -529,6 +549,7 @@ extension FileDescriptor { case _DT_SOCK: return .socket default: return .unknown } +#endif } } @@ -657,7 +678,7 @@ public enum FileTime { public typealias FileTime = Clock.TimeSpec #endif -#if !os(Windows) +#if !os(Windows) && !os(WASI) // MARK: - Synchronized Input and Output diff --git a/Sources/SystemExtras/Syscalls.swift b/Sources/SystemExtras/Syscalls.swift index 3a8aa578..00ee641f 100644 --- a/Sources/SystemExtras/Syscalls.swift +++ b/Sources/SystemExtras/Syscalls.swift @@ -12,6 +12,8 @@ import Android #elseif os(Windows) import ucrt import WinSDK +#elseif os(WASI) +import WASILibc #else #error("Unsupported Platform") #endif @@ -127,7 +129,7 @@ internal func system_symlinkat( extension CInterop { #if SYSTEM_PACKAGE_DARWIN public typealias DirP = UnsafeMutablePointer - #elseif os(Linux) || os(Android) + #elseif os(Linux) || os(Android) || os(WASI) public typealias DirP = OpaquePointer #else #error("Unsupported Platform") diff --git a/Sources/WASI/Clock.swift b/Sources/WASI/Clock.swift index c84aee5c..8b096b82 100644 --- a/Sources/WASI/Clock.swift +++ b/Sources/WASI/Clock.swift @@ -92,12 +92,10 @@ public protocol MonotonicClock { /// A monotonic clock that uses the system's monotonic clock. public struct SystemMonotonicClock: MonotonicClock { private var underlying: SystemExtras.Clock { - #if os(Linux) || os(Android) + #if os(Linux) || os(Android) || os(WASI) return .monotonic #elseif os(macOS) || os(iOS) || os(watchOS) || os(tvOS) || os(visionOS) return .rawUptime - #elseif os(WASI) - return .monotonic #elseif os(OpenBSD) || os(FreeBSD) return .uptime #else diff --git a/Sources/WASI/Platform/PlatformTypes.swift b/Sources/WASI/Platform/PlatformTypes.swift index 6b0637ac..9d0be178 100644 --- a/Sources/WASI/Platform/PlatformTypes.swift +++ b/Sources/WASI/Platform/PlatformTypes.swift @@ -40,15 +40,17 @@ extension WASIAbi.Fdflags { if platformOpenOptions.contains(.append) { fdFlags.insert(.APPEND) } - if platformOpenOptions.contains(.dataSync) { - fdFlags.insert(.DSYNC) - } if platformOpenOptions.contains(.nonBlocking) { fdFlags.insert(.NONBLOCK) } - if platformOpenOptions.contains(.fileSync) { - fdFlags.insert(.SYNC) - } + #if !os(WASI) + if platformOpenOptions.contains(.dataSync) { + fdFlags.insert(.DSYNC) + } + if platformOpenOptions.contains(.fileSync) { + fdFlags.insert(.SYNC) + } + #endif #if os(Linux) if platformOpenOptions.contains(.readSync) { fdFlags.insert(.RSYNC) @@ -64,15 +66,17 @@ extension WASIAbi.Fdflags { flags.insert(.append) } #if !os(Windows) - if self.contains(.DSYNC) { - flags.insert(.dataSync) - } if self.contains(.NONBLOCK) { flags.insert(.nonBlocking) } - if self.contains(.SYNC) { - flags.insert(.fileSync) - } + #if !os(WASI) + if self.contains(.DSYNC) { + flags.insert(.dataSync) + } + if self.contains(.SYNC) { + flags.insert(.fileSync) + } + #endif #if os(Linux) if self.contains(.RSYNC) { flags.insert(.readSync) diff --git a/Sources/WASI/Platform/SandboxPrimitives/Open.swift b/Sources/WASI/Platform/SandboxPrimitives/Open.swift index a99f7bd0..d3439571 100644 --- a/Sources/WASI/Platform/SandboxPrimitives/Open.swift +++ b/Sources/WASI/Platform/SandboxPrimitives/Open.swift @@ -15,6 +15,8 @@ import SystemPackage #elseif os(Windows) import CSystem import ucrt +#elseif os(WASI) + import WASILibc #else #error("Unsupported Platform") #endif @@ -127,13 +129,17 @@ struct PathResolution { throw openErrno } - try self.symlink(component: component) + #if os(WASI) + throw Errno.notSupported + #else + try self.symlink(component: component) + #endif #endif } } } - #if !os(Windows) + #if !os(Windows) && !os(WASI) mutating func symlink(component: FilePath.Component) throws { /// Thin wrapper around readlinkat(2) func _readlinkat(_ fd: CInt, _ path: UnsafePointer) throws -> FilePath { diff --git a/Sources/WASI/WASI.swift b/Sources/WASI/WASI.swift index 1e4896e5..5bd648ce 100644 --- a/Sources/WASI/WASI.swift +++ b/Sources/WASI/WASI.swift @@ -12,6 +12,8 @@ import WasmTypes import Android #elseif os(Windows) import ucrt +#elseif os(WASI) + import WASILibc #else #error("Unsupported Platform") #endif @@ -1391,7 +1393,7 @@ public class WASIBridgeToHost: WASI { fdTable[2] = .file(StdioFileEntry(fd: stderr, accessMode: .write)) for (guestPath, hostPath) in preopens { - #if os(Windows) + #if os(Windows) || os(WASI) let fd = try FileDescriptor.open(FilePath(hostPath), .readWrite) #else let fd = try hostPath.withCString { cHostPath in diff --git a/Sources/WIT/PackageResolver.swift b/Sources/WIT/PackageResolver.swift index cfd1e29a..2bd95145 100644 --- a/Sources/WIT/PackageResolver.swift +++ b/Sources/WIT/PackageResolver.swift @@ -195,52 +195,49 @@ extension SourceFileSyntax { } } -#if !os(WASI) - /// A ``PackageFileLoader`` adapter for local file system. - public struct LocalFileLoader: PackageFileLoader { - public typealias FilePath = String +/// A ``PackageFileLoader`` adapter for local file system. +public struct LocalFileLoader: PackageFileLoader { + public typealias FilePath = String - let fileManager: FileManager + let fileManager: FileManager - public init(fileManager: FileManager = .default) { - self.fileManager = fileManager - } - - enum Error: Swift.Error { - case failedToLoadFile(FilePath) - } + public init(fileManager: FileManager = .default) { + self.fileManager = fileManager + } - private func isDirectory(filePath: String) -> Bool { - var isDirectory: ObjCBool = false - let exists = fileManager.fileExists(atPath: filePath, isDirectory: &isDirectory) - return exists && isDirectory.boolValue - } + enum Error: Swift.Error { + case failedToLoadFile(FilePath) + } - public func contentsOfWITFile(at filePath: String) throws -> String { - guard let bytes = fileManager.contents(atPath: filePath) else { - throw Error.failedToLoadFile(filePath) - } - return String(decoding: bytes, as: UTF8.self) - } + private func isDirectory(filePath: String) -> Bool { + var isDirectory: ObjCBool = false + let exists = fileManager.fileExists(atPath: filePath, isDirectory: &isDirectory) + return exists && isDirectory.boolValue + } - public func packageFiles(in packageDirectory: String) throws -> [String] { - let dirURL = URL(fileURLWithPath: packageDirectory) - return try fileManager.contentsOfDirectory(atPath: packageDirectory).filter { fileName in - return fileName.hasSuffix(".wit") - && { - let filePath = dirURL.appendingPathComponent(fileName) - return !isDirectory(filePath: filePath.path) - }() - } - .map { dirURL.appendingPathComponent($0).path } + public func contentsOfWITFile(at filePath: String) throws -> String { + guard let bytes = fileManager.contents(atPath: filePath) else { + throw Error.failedToLoadFile(filePath) } + return String(decoding: bytes, as: UTF8.self) + } - public func dependencyDirectories(from packageDirectory: String) throws -> [String] { - let dirURL = URL(fileURLWithPath: packageDirectory) - let depsDir = dirURL.appendingPathComponent("deps") - guard isDirectory(filePath: depsDir.path) else { return [] } - return try fileManager.contentsOfDirectory(atPath: depsDir.path) + public func packageFiles(in packageDirectory: String) throws -> [String] { + let dirURL = URL(fileURLWithPath: packageDirectory) + return try fileManager.contentsOfDirectory(atPath: packageDirectory).filter { fileName in + return fileName.hasSuffix(".wit") + && { + let filePath = dirURL.appendingPathComponent(fileName) + return !isDirectory(filePath: filePath.path) + }() } + .map { dirURL.appendingPathComponent($0).path } } -#endif + public func dependencyDirectories(from packageDirectory: String) throws -> [String] { + let dirURL = URL(fileURLWithPath: packageDirectory) + let depsDir = dirURL.appendingPathComponent("deps") + guard isDirectory(filePath: depsDir.path) else { return [] } + return try fileManager.contentsOfDirectory(atPath: depsDir.path) + } +} diff --git a/Sources/WITExtractor/SwiftAPIDigester.swift b/Sources/WITExtractor/SwiftAPIDigester.swift index 5c6b2604..a60c6d93 100644 --- a/Sources/WITExtractor/SwiftAPIDigester.swift +++ b/Sources/WITExtractor/SwiftAPIDigester.swift @@ -118,7 +118,7 @@ struct SwiftAPIDigester { @available(macOS 11, iOS 14.0, watchOS 7.0, tvOS 14.0, *) func dumpSDK(moduleName: String, arguments: [String]) throws -> Output { - #if os(iOS) || os(watchOS) || os(tvOS) || os(visionOS) + #if os(iOS) || os(watchOS) || os(tvOS) || os(visionOS) || os(WASI) fatalError("WITExtractor does not support platforms where Foundation.Process is unavailable") #else var args = [ diff --git a/Sources/WasmKit/Engine.swift b/Sources/WasmKit/Engine.swift index c559fa47..d8f82b5c 100644 --- a/Sources/WasmKit/Engine.swift +++ b/Sources/WasmKit/Engine.swift @@ -48,7 +48,11 @@ public struct EngineConfiguration { } static var defaultForCurrentPlatform: ThreadingModel { - return useDirectThreadedCode ? .direct : .token + #if os(WASI) + return .token + #else + return useDirectThreadedCode ? .direct : .token + #endif } } diff --git a/Sources/WasmKit/Execution/DispatchInstruction.swift b/Sources/WasmKit/Execution/DispatchInstruction.swift index e21fa2f6..51f0a288 100644 --- a/Sources/WasmKit/Execution/DispatchInstruction.swift +++ b/Sources/WasmKit/Execution/DispatchInstruction.swift @@ -1933,11 +1933,15 @@ extension Execution { extension Instruction { /// The tail-calling execution handler for the instruction. var handler: UInt { + #if os(WASI) + fatalError("Direct threading is not supported on WASI") + #else return withUnsafePointer(to: wasmkit_tc_exec_handlers) { let count = MemoryLayout.size(ofValue: wasmkit_tc_exec_handlers) / MemoryLayout.size return $0.withMemoryRebound(to: UInt.self, capacity: count) { $0[Int(self.opcodeID)] } } + #endif } } diff --git a/Sources/WasmKit/Execution/Execution.swift b/Sources/WasmKit/Execution/Execution.swift index 4f86cb75..b0d09dfa 100644 --- a/Sources/WasmKit/Execution/Execution.swift +++ b/Sources/WasmKit/Execution/Execution.swift @@ -400,21 +400,25 @@ extension Execution { mutating func runDirectThreaded( sp: Sp, pc: Pc, md: Md, ms: Ms ) throws { - var pc = pc - let handler = pc.read(wasmkit_tc_exec.self) - wasmkit_tc_start(handler, sp, pc, md, ms, &self) - if let (rawError, trappingSp) = self.trap { - let error = unsafeBitCast(rawError, to: Error.self) - // Manually release the error object because the trap is caught in C and - // held as a raw pointer. - wasmkit_swift_errorRelease(rawError) - - guard let trap = error as? Trap else { - throw error + #if os(WASI) + fatalError("Direct threading is not supported on WASI") + #else + var pc = pc + let handler = pc.read(wasmkit_tc_exec.self) + wasmkit_tc_start(handler, sp, pc, md, ms, &self) + if let (rawError, trappingSp) = self.trap { + let error = unsafeBitCast(rawError, to: Error.self) + // Manually release the error object because the trap is caught in C and + // held as a raw pointer. + wasmkit_swift_errorRelease(rawError) + + guard let trap = error as? Trap else { + throw error + } + // Attach backtrace if the thrown error is a trap + throw trap.withBacktrace(Self.captureBacktrace(sp: trappingSp, store: store.value)) } - // Attach backtrace if the thrown error is a trap - throw trap.withBacktrace(Self.captureBacktrace(sp: trappingSp, store: store.value)) - } + #endif } #if EngineStats diff --git a/Sources/_CWasmKit/include/Platform.h b/Sources/_CWasmKit/include/Platform.h index ec4ef3c1..65ab4099 100644 --- a/Sources/_CWasmKit/include/Platform.h +++ b/Sources/_CWasmKit/include/Platform.h @@ -5,7 +5,7 @@ // rather than a language standard feature after LLVM 19. We check // `__has_attribute(swiftasynccc)` too for compatibility with older versions. // See https://github.com/llvm/llvm-project/pull/85347 -#if __has_feature(swiftasynccc) || __has_extension(swiftasynccc) +#if !defined(__wasi__) && (__has_feature(swiftasynccc) || __has_extension(swiftasynccc)) # define WASMKIT_HAS_SWIFTASYNCCC 1 #else # define WASMKIT_HAS_SWIFTASYNCCC 0 diff --git a/Sources/_CWasmKit/include/_CWasmKit.h b/Sources/_CWasmKit/include/_CWasmKit.h index ad7e41d1..6876aa37 100644 --- a/Sources/_CWasmKit/include/_CWasmKit.h +++ b/Sources/_CWasmKit/include/_CWasmKit.h @@ -17,6 +17,7 @@ typedef void *_Nullable Pc; typedef void *_Nullable Md; typedef size_t Ms; +#if WASMKIT_USE_DIRECT_THREADED_CODE /// The function type for executing a single instruction and transitioning to /// the next instruction by tail calling. `swiftasync` calling convention is /// used to keep `state` in the context register and to force tail calling. @@ -40,6 +41,7 @@ static inline void wasmkit_tc_start( ) { exec(sp, pc, md, ms, state); } +#endif static inline void wasmkit_fwrite_stderr(const char *_Nonnull str, size_t len) { fwrite(str, 1, len, stderr); diff --git a/Utilities/Sources/VMGen.swift b/Utilities/Sources/VMGen.swift index dabb0b5b..c82b8645 100644 --- a/Utilities/Sources/VMGen.swift +++ b/Utilities/Sources/VMGen.swift @@ -463,12 +463,16 @@ enum VMGen { extension Instruction { /// The tail-calling execution handler for the instruction. var handler: UInt { + #if os(WASI) + fatalError("Direct threading is not supported on WASI") + #else return withUnsafePointer(to: wasmkit_tc_exec_handlers) { let count = MemoryLayout.size(ofValue: wasmkit_tc_exec_handlers) / MemoryLayout.size return $0.withMemoryRebound(to: UInt.self, capacity: count) { $0[Int(self.opcodeID)] } } + #endif } }