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] = []