Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// swift-tools-version:6.3
// Note: swift-tools-version is kept at 6.3 for compatibility; the embedded Swift
// build uses WasmParserCore and WasmKit directly with -enable-experimental-feature Embedded.

import PackageDescription

Expand Down Expand Up @@ -33,6 +35,9 @@ let package = Package(
.library(name: "WasmKitWASI", targets: ["WasmKitWASI"]),
.library(name: "WASI", targets: ["WASI"]),
.library(name: "WasmParser", targets: ["WasmParser"]),
// WasmParserCore is the embedded-Swift-compatible subset of WasmParser
// (no file I/O, no SystemPackage dependency).
.library(name: "WasmParserCore", targets: ["WasmParserCore"]),
.library(name: "WAT", targets: ["WAT"]),
.library(name: "WIT", targets: ["WIT"]),
.library(name: "_CabiShims", targets: ["_CabiShims"]),
Expand All @@ -54,10 +59,14 @@ let package = Package(
name: "WasmKit",
dependencies: [
"_CWasmKit",
"WasmParser",
"WasmParserCore",
"WasmTypes",
"SystemExtras",
.product(name: "SystemPackage", package: "swift-system"),
// WasmParser (file I/O), SystemExtras, and SystemPackage are only available on
// OS-bearing platforms. Bare-metal / embedded targets skip these deps, which
// allows WasmKit to compile with -enable-experimental-feature Embedded.
.target(name: "WasmParser", condition: .when(platforms: [.macOS, .iOS, .watchOS, .tvOS, .visionOS, .linux, .android, .windows, .wasi])),
.target(name: "SystemExtras", condition: .when(platforms: [.macOS, .iOS, .watchOS, .tvOS, .visionOS, .linux, .android, .windows, .wasi])),
.product(name: "SystemPackage", package: "swift-system", condition: .when(platforms: [.macOS, .iOS, .watchOS, .tvOS, .visionOS, .linux, .android, .windows, .wasi])),
.target(
name: "ComponentModel",
condition: .when(traits: ["ComponentModel"])
Expand Down Expand Up @@ -109,15 +118,21 @@ let package = Package(
),

.target(
name: "WasmParser",
name: "WasmParserCore",
dependencies: [
"SystemExtras",
"WasmTypes",
.product(name: "SystemPackage", package: "swift-system"),
.target(
name: "ComponentModel",
condition: .when(traits: ["ComponentModel"])
),
]
),
.target(
name: "WasmParser",
dependencies: [
"WasmParserCore",
.product(name: "SystemPackage", package: "swift-system"),
],
exclude: ["CMakeLists.txt"],
swiftSettings: swiftSettings
Expand All @@ -126,6 +141,7 @@ let package = Package(
name: "WasmParserTests",
dependencies: [
"WasmParser",
"WasmParserCore",
.target(
name: "ComponentModel",
condition: .when(traits: ["ComponentModel"])
Expand Down
20 changes: 19 additions & 1 deletion Sources/WasmKit/Engine.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import _CWasmKit.Platform

import struct WasmParser.WasmFeatureSet
import WasmParserCore

/// A WebAssembly execution engine.
///
Expand All @@ -12,14 +12,17 @@ public final class Engine {

/// The engine configuration.
public let configuration: EngineConfiguration
#if !$Embedded
let interceptor: EngineInterceptor?
#endif
let funcTypeInterner: Interner<FunctionType>

/// Create a new execution engine.
///
/// - Parameters:
/// - configuration: The engine configuration.
/// - interceptor: An optional runtime interceptor to intercept execution of instructions.
#if !$Embedded
public init(
configuration: EngineConfiguration = EngineConfiguration(),
interceptor: EngineInterceptor? = nil
Expand All @@ -40,6 +43,21 @@ public final class Engine {
self.interceptor = interceptor
self.funcTypeInterner = Interner()
}
#else
public init(configuration: EngineConfiguration = EngineConfiguration()) {
var configuration = configuration

if WASMKIT_MPROTECT_BOUND_CHECKING == 0
|| Engine.isAddressSanitizerEnabled
|| (configuration.memoryBoundsChecking == .mprotect && configuration.threadingModel == .token)
{
configuration.memoryBoundsChecking = .software
}

self.configuration = configuration
self.funcTypeInterner = Interner()
}
#endif

/// Migration aid for the old ``Runtime/instantiate(module:)``
@available(*, unavailable, message: "Use ``Module/instantiate(store:imports:)`` instead")
Expand Down
4 changes: 4 additions & 0 deletions Sources/WasmKit/Execution/AtomicParkingLot.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Embedded Swift does not support the Synchronization framework; this entire file
// is excluded from embedded builds.
#if !$Embedded
/// Synchronization primitives for atomic memory wait and notify operations.
///
/// Provides thread-safe waiting and notification mechanisms for shared memory
Expand Down Expand Up @@ -174,3 +177,4 @@ enum WaitOutcome {
case mismatch // 1 - value didn't match expected
case timedOut // 2 - deadline expired
}
#endif // !$Embedded
26 changes: 14 additions & 12 deletions Sources/WasmKit/Execution/ConstEvaluation.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import WasmParser
import WasmParserCore

protocol ConstEvaluationContextProtocol {
func functionRef(_ index: FunctionIndex) throws -> Reference
func globalValue(_ index: GlobalIndex) throws -> Value
func functionRef(_ index: FunctionIndex) throws(WasmKitError) -> Reference
func globalValue(_ index: GlobalIndex) throws(WasmKitError) -> Value
}

struct ConstEvaluationContext: ConstEvaluationContextProtocol {
Expand All @@ -28,12 +28,12 @@ struct ConstEvaluationContext: ConstEvaluationContextProtocol {
self.init(functions: instance.functions, globals: Array(externalGlobals))
}

func functionRef(_ index: FunctionIndex) throws -> Reference {
func functionRef(_ index: FunctionIndex) throws(WasmKitError) -> Reference {
let function = try self.functions[validating: Int(index)]
self.onFunctionReferenced?(function)
return .function(from: function)
}
func globalValue(_ index: GlobalIndex) throws -> Value {
func globalValue(_ index: GlobalIndex) throws(WasmKitError) -> Value {
guard index < globals.count else {
throw GlobalEntity.createOutOfBoundsError(index: Int(index), count: globals.count)
}
Expand All @@ -42,13 +42,13 @@ struct ConstEvaluationContext: ConstEvaluationContextProtocol {
}

extension ConstExpression {
func evaluate<C: ConstEvaluationContextProtocol>(context: C, expectedType: WasmTypes.ValueType) throws -> Value {
func evaluate<C: ConstEvaluationContextProtocol>(context: C, expectedType: WasmTypes.ValueType) throws(WasmKitError) -> Value {
let result = try self._evaluate(context: context)
try result.checkType(expectedType)
return result
}

private func _evaluate<C: ConstEvaluationContextProtocol>(context: C) throws -> Value {
private func _evaluate<C: ConstEvaluationContextProtocol>(context: C) throws(WasmKitError) -> Value {
guard self.last == .end, self.count == 2 else {
throw WasmKitError(message: .expectedEndAtOffsetExpression)
}
Expand Down Expand Up @@ -77,17 +77,19 @@ extension ConstExpression {
}
}

extension WasmParser.ElementSegment {
func evaluateInits<C: ConstEvaluationContextProtocol>(context: C) throws -> [Reference] {
return try self.initializer.map { expression -> Reference in
extension WasmParserCore.ElementSegment {
func evaluateInits<C: ConstEvaluationContextProtocol>(context: C) throws(WasmKitError) -> [Reference] {
var results: [Reference] = []
for expression in self.initializer {
let result = try Self._evaluateInits(context: context, expression: expression)
try result.checkType(self.type)
return result
results.append(result)
}
return results
}
static func _evaluateInits<C: ConstEvaluationContextProtocol>(
context: C, expression: ConstExpression
) throws -> Reference {
) throws(WasmKitError) -> Reference {
switch expression[0] {
case .refFunc(let index):
return try context.functionRef(index)
Expand Down
Loading
Loading