From 71c075536270ab5a4d27feb9badb9c7908234bad Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Tue, 25 Mar 2025 10:34:15 +0000 Subject: [PATCH] Parse `.wat` files in the `run` subcommand WasmKit already supports parsing of WAT (WebAssembly Text format), but its command-line interface does not act accordingly for files with `.wat` file extension. This change conditionally parses the text format on matching file extension instead of assuming that all given files are in binary format. --- Package.swift | 1 + Sources/CLI/CMakeLists.txt | 2 +- Sources/CLI/Commands/Run.swift | 22 ++++++++++++++++++++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Package.swift b/Package.swift index 1e31ce82..a9afdd1f 100644 --- a/Package.swift +++ b/Package.swift @@ -28,6 +28,7 @@ let package = Package( .executableTarget( name: "CLI", dependencies: [ + "WAT", "WasmKit", "WasmKitWASI", .product(name: "ArgumentParser", package: "swift-argument-parser"), diff --git a/Sources/CLI/CMakeLists.txt b/Sources/CLI/CMakeLists.txt index 27da5679..c72d81bf 100644 --- a/Sources/CLI/CMakeLists.txt +++ b/Sources/CLI/CMakeLists.txt @@ -5,7 +5,7 @@ add_executable(wasmkit-cli ) target_link_wasmkit_libraries(wasmkit-cli PUBLIC - ArgumentParser WasmKitWASI) + ArgumentParser WAT WasmKitWASI) install(TARGETS wasmkit-cli RUNTIME DESTINATION bin) diff --git a/Sources/CLI/Commands/Run.swift b/Sources/CLI/Commands/Run.swift index e7461fae..3c690e81 100644 --- a/Sources/CLI/Commands/Run.swift +++ b/Sources/CLI/Commands/Run.swift @@ -1,5 +1,6 @@ import ArgumentParser import SystemPackage +import WAT import WasmKit import WasmKitWASI @@ -119,12 +120,12 @@ struct Run: ParsableCommand { let module: Module if verbose, #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) { let (parsedModule, parseTime) = try measure { - try parseWasm(filePath: FilePath(path)) + try self.parseWasm(filePath: FilePath(path)) } log("Finished parsing module: \(parseTime)", verbose: true) module = parsedModule } else { - module = try parseWasm(filePath: FilePath(path)) + module = try self.parseWasm(filePath: FilePath(path)) } let (interceptor, finalize) = try deriveInterceptor() @@ -148,6 +149,23 @@ struct Run: ParsableCommand { } } + /// Parses a `.wasm` or `.wat` module. + func parseWasm(filePath: FilePath) throws -> Module { + if filePath.extension == "wat", #available(macOS 11.0, iOS 14.0, macCatalyst 14.0, tvOS 14.0, visionOS 1.0, watchOS 7.0, *) { + let fileHandle = try FileDescriptor.open(filePath, .readOnly) + defer { try? fileHandle.close() } + + let size = try fileHandle.seek(offset: 0, from: .end) + + let wat = try String(unsafeUninitializedCapacity: Int(size)) { + try fileHandle.read(fromAbsoluteOffset: 0, into: .init($0)) + } + return try WasmKit.parseWasm(bytes: wat2wasm(wat)) + } else { + return try WasmKit.parseWasm(filePath: filePath) + } + } + /// Derives the runtime interceptor based on the command line arguments func deriveInterceptor() throws -> (interceptor: EngineInterceptor?, finalize: () -> Void) { var interceptors: [EngineInterceptor] = []