diff --git a/Sources/Spectest/TestCase.swift b/Sources/Spectest/TestCase.swift index 3e28d18e..98c2b1ca 100644 --- a/Sources/Spectest/TestCase.swift +++ b/Sources/Spectest/TestCase.swift @@ -546,8 +546,6 @@ extension Swift.Error { return "data count and data section have inconsistent lengths" case .expectedRefType: return "malformed reference type" - case .unexpectedContent: - return "unexpected content after last section" case .sectionSizeMismatch: return "section size mismatch" case .illegalOpcode: diff --git a/Sources/WasmKit/Component/ComponentTypes.swift b/Sources/WasmKit/Component/ComponentTypes.swift index 0cffd905..1f4965d8 100644 --- a/Sources/WasmKit/Component/ComponentTypes.swift +++ b/Sources/WasmKit/Component/ComponentTypes.swift @@ -1,6 +1,9 @@ +/// Error type raised from Component Model operations public struct ComponentError: Error { + /// The content of the error public let content: Content + /// Initialize a new error with the given content public init(_ content: Content) { self.content = content } diff --git a/Sources/WasmKit/Docs.docc/Docs.md b/Sources/WasmKit/Docs.docc/Docs.md index 28585dd2..196423e7 100644 --- a/Sources/WasmKit/Docs.docc/Docs.md +++ b/Sources/WasmKit/Docs.docc/Docs.md @@ -93,8 +93,3 @@ _ = try runtime.invoke(instance, function: "_start") - ``CanonicalOptions`` - ``CanonicalCallContext`` - ``ComponentError`` - -### Hook Runtime - -- ``RuntimeInterceptor`` -- ``GuestTimeProfiler`` diff --git a/Sources/WasmKit/Execution/Runtime/GuestMemory.swift b/Sources/WasmKit/Execution/Runtime/GuestMemory.swift index 30854db4..301f436f 100644 --- a/Sources/WasmKit/Execution/Runtime/GuestMemory.swift +++ b/Sources/WasmKit/Execution/Runtime/GuestMemory.swift @@ -3,6 +3,7 @@ public struct GuestMemory { private let store: Store private let address: MemoryAddress + /// Creates a new memory instance from the given store and address public init(store: Store, address: MemoryAddress) { self.store = store self.address = address @@ -47,17 +48,21 @@ extension GuestPrimitivePointee { } } +/// Auto implementation of ``GuestPointee`` for ``RawRepresentable`` types extension GuestPrimitivePointee where Self: RawRepresentable, Self.RawValue: GuestPointee { + /// Reads a value of RawValue type and constructs a value of Self type public static func readFromGuest(_ pointer: UnsafeGuestRawPointer) -> Self { Self(rawValue: .readFromGuest(pointer))! } + /// Writes the raw value of the given value to the given pointer of guest memory public static func writeToGuest(at pointer: UnsafeGuestRawPointer, value: Self) { Self.RawValue.writeToGuest(at: pointer, value: value.rawValue) } } extension UInt8: GuestPrimitivePointee { + /// Reads a value of `UInt8` type from the given pointer of guest memory public static func readFromGuest(_ pointer: UnsafeGuestRawPointer) -> UInt8 { pointer.withHostPointer { hostPointer in let pointer = hostPointer.assumingMemoryBound(to: UInt8.self) @@ -65,6 +70,7 @@ extension UInt8: GuestPrimitivePointee { } } + /// Writes the given value at the given pointer of guest memory public static func writeToGuest(at pointer: UnsafeGuestRawPointer, value: UInt8) { pointer.withHostPointer { hostPointer in let pointer = hostPointer.assumingMemoryBound(to: UInt8.self) @@ -74,6 +80,7 @@ extension UInt8: GuestPrimitivePointee { } extension UInt16: GuestPrimitivePointee { + /// Reads a value of `UInt16` type from the given pointer of guest memory public static func readFromGuest(_ pointer: UnsafeGuestRawPointer) -> UInt16 { pointer.withHostPointer { hostPointer in let pointer = hostPointer.assumingMemoryBound(to: UInt16.self) @@ -86,6 +93,7 @@ extension UInt16: GuestPrimitivePointee { } } + /// Writes the given value at the given pointer of guest memory public static func writeToGuest(at pointer: UnsafeGuestRawPointer, value: UInt16) { pointer.withHostPointer { hostPointer in let pointer = hostPointer.assumingMemoryBound(to: UInt16.self) @@ -101,6 +109,7 @@ extension UInt16: GuestPrimitivePointee { } extension UInt32: GuestPrimitivePointee { + /// Reads a value of `UInt32` type from the given pointer of guest memory public static func readFromGuest(_ pointer: UnsafeGuestRawPointer) -> UInt32 { pointer.withHostPointer { hostPointer in let pointer = hostPointer.assumingMemoryBound(to: UInt32.self) @@ -113,6 +122,7 @@ extension UInt32: GuestPrimitivePointee { } } + /// Writes the given value at the given pointer of guest memory public static func writeToGuest(at pointer: UnsafeGuestRawPointer, value: UInt32) { pointer.withHostPointer { hostPointer in let pointer = hostPointer.assumingMemoryBound(to: UInt32.self) @@ -128,6 +138,7 @@ extension UInt32: GuestPrimitivePointee { } extension UInt64: GuestPrimitivePointee { + /// Reads a value of `UInt64` type from the given pointer of guest memory public static func readFromGuest(_ pointer: UnsafeGuestRawPointer) -> UInt64 { pointer.withHostPointer { hostPointer in let pointer = hostPointer.assumingMemoryBound(to: UInt64.self) @@ -140,6 +151,7 @@ extension UInt64: GuestPrimitivePointee { } } + /// Writes the given value at the given pointer of guest memory public static func writeToGuest(at pointer: UnsafeGuestRawPointer, value: UInt64) { pointer.withHostPointer { hostPointer in let pointer = hostPointer.assumingMemoryBound(to: UInt64.self) @@ -162,6 +174,7 @@ public struct UnsafeGuestRawPointer { /// An offset from the base address of the guest memory region public let offset: UInt32 + /// Creates a new pointer from the given memory space and offset public init(memorySpace: GuestMemory, offset: UInt32) { self.memorySpace = memorySpace self.offset = offset @@ -193,29 +206,39 @@ public struct UnsafeGuestRawPointer { } extension UnsafeGuestRawPointer: GuestPointee { + /// Returns the size of this type in bytes in guest memory public static var sizeInGuest: UInt32 { return UInt32(MemoryLayout.size) } + /// Returns the required alignment of this type, in bytes public static var alignInGuest: UInt32 { return UInt32(MemoryLayout.alignment) } + /// Reads a value of self type from the given pointer of guest memory public static func readFromGuest(_ pointer: UnsafeGuestRawPointer) -> UnsafeGuestRawPointer { UnsafeGuestRawPointer(memorySpace: pointer.memorySpace, offset: UInt32.readFromGuest(pointer)) } + /// Writes the given value at the given pointer of guest memory public static func writeToGuest(at pointer: UnsafeGuestRawPointer, value: UnsafeGuestRawPointer) { UInt32.writeToGuest(at: pointer, value: value.offset) } } extension UnsafeGuestRawPointer { + /// Returns a boolean value indicating whether the first pointer references a guest + /// memory location earlier than the second pointer assuming they point the same guest + /// memory space. public static func < (lhs: UnsafeGuestRawPointer, rhs: UnsafeGuestRawPointer) -> Bool { // Assuming they point the same guest memory space lhs.offset < rhs.offset } + /// Returns a boolean value indicating whether the first pointer references a guest + /// memory location later than the second pointer assuming they point the same guest + /// memory space. public static func > (lhs: UnsafeGuestRawPointer, rhs: UnsafeGuestRawPointer) -> Bool { // Assuming they point the same guest memory space lhs.offset > rhs.offset @@ -224,12 +247,15 @@ extension UnsafeGuestRawPointer { /// A pointee-bound pointer representation of guest memory space public struct UnsafeGuestPointer { + /// A raw pointer representation of guest memory space public let raw: UnsafeGuestRawPointer + /// Creates a new pointer from the given raw pointer public init(_ raw: UnsafeGuestRawPointer) { self.raw = raw } + /// Creates a new pointer from the given memory space and offset public init(memorySpace: GuestMemory, offset: UInt32) { self.raw = UnsafeGuestRawPointer(memorySpace: memorySpace, offset: offset) } @@ -249,37 +275,49 @@ public struct UnsafeGuestPointer { } extension UnsafeGuestPointer: GuestPointee { + /// Returns the size of this type in bytes in guest memory public static var sizeInGuest: UInt32 { UnsafeGuestRawPointer.sizeInGuest } + /// Returns the required alignment of this type, in bytes public static var alignInGuest: UInt32 { UnsafeGuestRawPointer.alignInGuest } + /// Reads a value of self type from the given pointer of guest memory public static func readFromGuest(_ pointer: UnsafeGuestRawPointer) -> UnsafeGuestPointer { UnsafeGuestPointer(UnsafeGuestRawPointer.readFromGuest(pointer)) } + /// Writes the given value at the given pointer of guest memory public static func writeToGuest(at pointer: UnsafeGuestRawPointer, value: UnsafeGuestPointer) { UnsafeGuestRawPointer.writeToGuest(at: pointer, value: value.raw) } } extension UnsafeGuestPointer { + /// Returns a new pointer offset from this pointer by the specified number of instances. public static func + (lhs: UnsafeGuestPointer, rhs: UInt32) -> UnsafeGuestPointer { let advanced = lhs.raw.advanced(by: Pointee.sizeInGuest * rhs) return UnsafeGuestPointer(advanced) } + /// Returns a new pointer offset from this pointer by the specified number of instances. public static func += (lhs: inout Self, rhs: UInt32) { lhs = lhs + rhs } + /// Returns a boolean value indicating whether the first pointer references a guest + /// memory location earlier than the second pointer assuming they point the same guest + /// memory space. public static func < (lhs: UnsafeGuestPointer, rhs: UnsafeGuestPointer) -> Bool { lhs.raw < rhs.raw } + /// Returns a boolean value indicating whether the first pointer references a guest + /// memory location later than the second pointer assuming they point the same guest + /// memory space. public static func > (lhs: UnsafeGuestPointer, rhs: UnsafeGuestPointer) -> Bool { lhs.raw > rhs.raw } @@ -287,9 +325,12 @@ extension UnsafeGuestPointer { /// A pointee-bound interface to a buffer of elements stored contiguously in guest memory public struct UnsafeGuestBufferPointer { + /// A pointer to the first element of the buffer public let baseAddress: UnsafeGuestPointer + /// The number of elements in the buffer public let count: UInt32 + /// Creates a new buffer from the given base address and count public init(baseAddress: UnsafeGuestPointer, count: UInt32) { self.baseAddress = baseAddress self.count = count diff --git a/Sources/WasmKit/Execution/Runtime/Profiler.swift b/Sources/WasmKit/Execution/Runtime/Profiler.swift index f55509fb..c13bef90 100644 --- a/Sources/WasmKit/Execution/Runtime/Profiler.swift +++ b/Sources/WasmKit/Execution/Runtime/Profiler.swift @@ -3,6 +3,8 @@ import SystemExtras import SystemPackage /// A simple time-profiler for guest process to emit `chrome://tracing` format +/// This profiler works only when WasmKit is built with debug configuration (`swift build -c debug`) +@_documentation(visibility: internal) public class GuestTimeProfiler: RuntimeInterceptor { struct Event: Codable { enum Phase: String, Codable { diff --git a/Sources/WasmKit/Execution/Runtime/Runtime.swift b/Sources/WasmKit/Execution/Runtime/Runtime.swift index 3d9a4978..9e4a97e3 100644 --- a/Sources/WasmKit/Execution/Runtime/Runtime.swift +++ b/Sources/WasmKit/Execution/Runtime/Runtime.swift @@ -11,6 +11,7 @@ public final class Runtime { } } +@_documentation(visibility: internal) public protocol RuntimeInterceptor { func onEnterFunction(_ address: FunctionAddress, store: Store) func onExitFunction(_ address: FunctionAddress, store: Store) diff --git a/Sources/WasmKit/Execution/Runtime/Stack.swift b/Sources/WasmKit/Execution/Runtime/Stack.swift index 1b0551ba..ebe0acc8 100644 --- a/Sources/WasmKit/Execution/Runtime/Stack.swift +++ b/Sources/WasmKit/Execution/Runtime/Stack.swift @@ -1,8 +1,7 @@ /// > Note: /// - -public struct Stack { - public enum Element: Equatable { +struct Stack { + enum Element: Equatable { case value(Value) case label(Label) case frame(Frame) @@ -296,7 +295,7 @@ struct BaseStackAddress { /// > Note: /// -public struct Frame { +struct Frame { let arity: Int let module: ModuleAddress let baseStackAddress: BaseStackAddress @@ -323,7 +322,7 @@ public struct Frame { } extension Frame: Equatable { - public static func == (_ lhs: Frame, _ rhs: Frame) -> Bool { + static func == (_ lhs: Frame, _ rhs: Frame) -> Bool { lhs.module == rhs.module && lhs.arity == rhs.arity } } @@ -341,7 +340,7 @@ extension Stack { } extension Frame: CustomDebugStringConvertible { - public var debugDescription: String { + var debugDescription: String { "[A=\(arity), BA=\(baseStackAddress), F=\(address?.description ?? "nil")]" } } diff --git a/Sources/WasmKit/Execution/Types/Errors.swift b/Sources/WasmKit/Execution/Types/Errors.swift index 3a1c6bf3..83dbdcda 100644 --- a/Sources/WasmKit/Execution/Types/Errors.swift +++ b/Sources/WasmKit/Execution/Types/Errors.swift @@ -5,33 +5,40 @@ public enum Trap: Error { case unreachable // Stack + /// Stack overflow case stackOverflow - case stackTypeMismatch(expected: Any.Type, actual: Stack.Element?) + /// The stack value type does not match the expected type case stackValueTypesMismatch(expected: ValueType, actual: ValueType) - case stackElementNotFound(Any.Type, index: Int) - case localIndexOutOfRange(index: UInt32) + /// Too deep call stack case callStackExhausted // Store - case globalAddressOutOfRange(index: GlobalAddress) - case globalImmutable(index: GlobalAddress) + /// Out of bounds table access case outOfBoundsTableAccess(index: ElementIndex) + /// Reading a dropped reference case readingDroppedReference(index: ElementIndex) // Invocation + /// Exported function not found case exportedFunctionNotFound(ModuleInstance, name: String) + /// The table element is not initialized case tableUninitialized(ElementIndex) + /// Undefined element in the table case undefinedElement + /// Table size overflow case tableSizeOverflow + /// Indirect call type mismatch case callIndirectFunctionTypeMismatch(actual: FunctionType, expected: FunctionType) + /// Out of bounds memory access case outOfBoundsMemoryAccess + /// Invalid function index case invalidFunctionIndex(FunctionIndex) - case poppedLabelMismatch - case labelMismatch + /// Integer divided by zero case integerDividedByZero + /// Integer overflowed during arithmetic operation case integerOverflowed + /// Invalid conversion to integer case invalidConversionToInteger - case tooManyBlockParameters([ValueType]) /// Human-readable text representation of the trap that `.wast` text format expects in assertions public var assertionText: String { diff --git a/Sources/WasmKit/Execution/Types/Instances.swift b/Sources/WasmKit/Execution/Types/Instances.swift index d0b81608..63f68040 100644 --- a/Sources/WasmKit/Execution/Types/Instances.swift +++ b/Sources/WasmKit/Execution/Types/Instances.swift @@ -146,6 +146,7 @@ public struct MemoryInstance { } } +/// Instance of a global /// > Note: /// public struct GlobalInstance { @@ -160,7 +161,7 @@ public struct GlobalInstance { /// > Note: /// -public struct ElementInstance { +struct ElementInstance { public let type: ReferenceType public var references: [Reference] @@ -171,9 +172,9 @@ public struct ElementInstance { /// > Note: /// -public struct DataInstance { +struct DataInstance { /// Bytes stored in this data instance. - public let data: [UInt8] + let data: [UInt8] } /// > Note: diff --git a/Sources/WasmKit/Execution/Types/Value.swift b/Sources/WasmKit/Execution/Types/Value.swift index 566798a7..36029dfe 100644 --- a/Sources/WasmKit/Execution/Types/Value.swift +++ b/Sources/WasmKit/Execution/Types/Value.swift @@ -1,23 +1,37 @@ /// > Note: /// +/// Numeric types public enum NumericType: Equatable { + /// Integer value type. case int(IntValueType) + /// Floating-point value type. case float(FloatValueType) + /// 32-bit signed or unsigned integer. public static let i32: Self = .int(.i32) + /// 64-bit signed or unsigned integer. public static let i64: Self = .int(.i64) + /// 32-bit IEEE 754 floating-point number. public static let f32: Self = .float(.f32) + /// 64-bit IEEE 754 floating-point number. public static let f64: Self = .float(.f64) } +/// Value types public enum ValueType: Equatable { + /// Numeric value type. case numeric(NumericType) + /// Reference value type. case reference(ReferenceType) + /// 32-bit signed or unsigned integer. public static let i32: Self = .numeric(.int(.i32)) + /// 64-bit signed or unsigned integer. public static let i64: Self = .numeric(.int(.i64)) + /// 32-bit IEEE 754 floating-point number. public static let f32: Self = .numeric(.float(.f32)) + /// 64-bit IEEE 754 floating-point number. public static let f64: Self = .numeric(.float(.f64)) var defaultValue: Value { @@ -71,21 +85,33 @@ extension ValueType: CustomStringConvertible { } } +/// Reference types public enum ReferenceType: Equatable { + /// A nullable reference type to a function. case funcRef + /// A nullable external reference type. case externRef } +/// Reference to a function. public enum Reference: Hashable { + /// A reference to a function. case function(FunctionAddress?) + /// A reference to an external entity. case extern(ExternAddress?) } +/// Runtime representation of a value. public enum Value: Hashable { + /// Value of a 32-bit signed or unsigned integer. case i32(UInt32) + /// Value of a 64-bit signed or unsigned integer. case i64(UInt64) + /// Value of a 32-bit IEEE 754 floating-point number. case f32(UInt32) + /// Value of a 64-bit IEEE 754 floating-point number. case f64(UInt64) + /// Reference value. case ref(Reference) var type: ValueType { @@ -116,37 +142,49 @@ public enum Value: Hashable { } } + /// Create a new value from a signed 32-bit integer. public init(signed value: Int32) { self = .i32(UInt32(bitPattern: value)) } + /// Create a new value from a signed 64-bit integer. public init(signed value: Int64) { self = .i64(UInt64(bitPattern: value)) } + /// Create a new value from a 32-bit floating-point number. public static func fromFloat32(_ value: Float32) -> Value { return .f32(value.bitPattern) } + /// Create a new value from a 64-bit floating-point number. public static func fromFloat64(_ value: Float64) -> Value { return .f64(value.bitPattern) } + /// Returns the value as a 32-bit signed integer. + /// - Precondition: The value is of type `i32`. public var i32: UInt32 { guard case let .i32(result) = self else { fatalError() } return result } + /// Returns the value as a 64-bit signed integer. + /// - Precondition: The value is of type `i64`. public var i64: UInt64 { guard case let .i64(result) = self else { fatalError() } return result } + /// Returns the value as a 32-bit floating-point number. + /// - Precondition: The value is of type `f32`. public var f32: UInt32 { guard case let .f32(result) = self else { fatalError() } return result } + /// Returns the value as a 64-bit floating-point number. + /// - Precondition: The value is of type `f64`. public var f64: UInt64 { guard case let .f64(result) = self else { fatalError() } return result @@ -156,6 +194,7 @@ public enum Value: Hashable { return isMemory64 ? i64 : UInt64(i32) } + /// Returns if the given values are equal. public static func == (lhs: Self, rhs: Self) -> Bool { switch (lhs, rhs) { case let (.i32(lhs), .i32(rhs)): @@ -177,6 +216,8 @@ public enum Value: Hashable { } extension Value: Comparable { + /// Returns if the left value is less than the right value. + /// - Precondition: The values are of the same type. public static func < (lhs: Self, rhs: Self) -> Bool { switch (lhs, rhs) { case let (.i32(lhs), .i32(rhs)): return lhs < rhs @@ -187,6 +228,8 @@ extension Value: Comparable { } } + /// Returns if the left value is greater than the right value. + /// - Precondition: The values are of the same type. public static func > (lhs: Self, rhs: Self) -> Bool { switch (lhs, rhs) { case let (.i32(lhs), .i32(rhs)): return lhs > rhs @@ -197,6 +240,8 @@ extension Value: Comparable { } } + /// Returns if the left value is less than or equal to the right value. + /// - Precondition: The values are of the same type. public static func >= (lhs: Self, rhs: Self) -> Bool { switch (lhs, rhs) { case let (.i32(lhs), .i32(rhs)): return lhs >= rhs @@ -207,6 +252,8 @@ extension Value: Comparable { } } + /// Returns if the left value is less than or equal to the right value. + /// - Precondition: The values are of the same type. public static func <= (lhs: Self, rhs: Self) -> Bool { switch (lhs, rhs) { case let (.i32(lhs), .i32(rhs)): return lhs <= rhs @@ -219,6 +266,7 @@ extension Value: Comparable { } extension Value: ExpressibleByBooleanLiteral { + /// Create a new value from a boolean literal. public init(booleanLiteral value: BooleanLiteralType) { if value { self = .i32(1) @@ -229,6 +277,7 @@ extension Value: ExpressibleByBooleanLiteral { } extension Value: CustomStringConvertible { + /// A textual representation of the value. public var description: String { switch self { case let .i32(rawValue): return "I32(\(rawValue.signed))" @@ -245,8 +294,11 @@ extension Value: CustomStringConvertible { /// > Note: /// +/// Integer value types public enum IntValueType { + /// 32-bit signed or unsigned integer. case i32 + /// 64-bit signed or unsigned integer. case i64 } @@ -297,8 +349,11 @@ extension RawSignedInteger { /// > Note: /// +/// Floating-point value types public enum FloatValueType { + /// 32-bit IEEE 754 floating-point number. case f32 + /// 64-bit IEEE 754 floating-point number. case f64 var nan: Value { diff --git a/Sources/WasmKit/Parser/Wasm/WasmParser.swift b/Sources/WasmKit/Parser/Wasm/WasmParser.swift index 324e0d8a..a4153264 100644 --- a/Sources/WasmKit/Parser/Wasm/WasmParser.swift +++ b/Sources/WasmKit/Parser/Wasm/WasmParser.swift @@ -17,17 +17,24 @@ final class WasmParser { } } +/// Flags for enabling/disabling WebAssembly features public struct WasmFeatureSet: OptionSet { + /// The raw value of the feature set public let rawValue: Int + /// Initialize a new feature set with the given raw value public init(rawValue: Int) { self.rawValue = rawValue } + /// The WebAssembly memory64 proposal public static let memory64 = WasmFeatureSet(rawValue: 1 << 0) + /// The WebAssembly reference types proposal public static let referenceTypes = WasmFeatureSet(rawValue: 1 << 1) + /// The default feature set public static let `default`: WasmFeatureSet = [.referenceTypes] + /// The feature set with all features enabled public static let all: WasmFeatureSet = [.memory64, .referenceTypes] } @@ -52,30 +59,53 @@ public func parseWasm(bytes: [UInt8], features: WasmFeatureSet = .default) throw } public enum WasmParserError: Swift.Error { + /// The magic number is not found or invalid case invalidMagicNumber([UInt8]) + /// The version is not recognized case unknownVersion([UInt8]) + /// The bytes are not valid UTF-8 case invalidUTF8([UInt8]) + /// The section has an invalid size case invalidSectionSize(UInt32) + /// The section ID is malformed case malformedSectionID(UInt8) + /// The byte is expected to be zero, but it's not case zeroExpected(actual: UInt8, index: Int) + /// The function and code length are inconsistent case inconsistentFunctionAndCodeLength(functionCount: Int, codeCount: Int) + /// The data count and data section length are inconsistent case inconsistentDataCountAndDataSectionLength(dataCount: UInt32, dataSection: Int) + /// The local count is too large case tooManyLocals + /// The type is expected to be a reference type, but it's not case expectedRefType(actual: ValueType) + /// The instruction is not implemented case unimplementedInstruction(UInt8, suffix: UInt32? = nil) + /// The element kind is unexpected case unexpectedElementKind(expected: UInt32, actual: UInt32) + /// The element kind is not recognized case integerRepresentationTooLong + /// `end` opcode is expected but not found case endOpcodeExpected + /// Unexpected end of the stream case unexpectedEnd - case unexpectedContent + /// The byte is not expected case sectionSizeMismatch(expected: Int, actual: Int) + /// Illegal opcode is found case illegalOpcode(UInt8) + /// Malformed mutability byte case malformedMutability(UInt8) + /// Malformed function type byte case malformedFunctionType(UInt8) + /// Sections in the module are out of order case sectionOutOfOrder + /// The data count section is required but not found case dataCountSectionRequired + /// Malformed limit byte case malformedLimit(UInt8) + /// Malformed indirect call case malformedIndirectCall + /// Invalid reference to a type section entry case invalidTypeSectionReference } diff --git a/Sources/WasmKit/Parser/Wasm/WasmTypes.swift b/Sources/WasmKit/Parser/Wasm/WasmTypes.swift index 3733b62e..7e7ed819 100644 --- a/Sources/WasmKit/Parser/Wasm/WasmTypes.swift +++ b/Sources/WasmKit/Parser/Wasm/WasmTypes.swift @@ -1,12 +1,12 @@ /// > Note: /// -public struct Code { +struct Code { let locals: [ValueType] let expression: ArraySlice } extension Code: Equatable { - public static func == (lhs: Code, rhs: Code) -> Bool { + static func == (lhs: Code, rhs: Code) -> Bool { return lhs.locals == rhs.locals && lhs.expression == rhs.expression } } diff --git a/Sources/WasmKit/Types/Module.swift b/Sources/WasmKit/Types/Module.swift index bfd58cc3..b7bef2a2 100644 --- a/Sources/WasmKit/Types/Module.swift +++ b/Sources/WasmKit/Types/Module.swift @@ -5,13 +5,13 @@ public struct Module { public internal(set) var types: [FunctionType] var functions: [GuestFunction] - public internal(set) var tables: [Table] - public internal(set) var memories: [Memory] - public internal(set) var globals: [Global] - public internal(set) var elements: [ElementSegment] - public internal(set) var dataCount: UInt32? - public internal(set) var data: [DataSegment] - public internal(set) var start: FunctionIndex? + var tables: [Table] + var memories: [Memory] + var globals: [Global] + var elements: [ElementSegment] + var dataCount: UInt32? + var data: [DataSegment] + var start: FunctionIndex? public internal(set) var imports: [Import] public internal(set) var exports: [Export] public internal(set) var customSections = [CustomSection]() @@ -48,23 +48,37 @@ public struct Module { } } +/// A custom section in a module public struct CustomSection: Equatable { public let name: String public let bytes: ArraySlice } -/// > Note: -/// +// MARK: - Module Entity Indices +// + +/// Index type for function types within a module public typealias TypeIndex = UInt32 +/// Index type for tables within a module public typealias FunctionIndex = UInt32 +/// Index type for tables within a module public typealias TableIndex = UInt32 +/// Index type for memories within a module public typealias MemoryIndex = UInt32 +/// Index type for globals within a module public typealias GlobalIndex = UInt32 +/// Index type for elements within a module public typealias ElementIndex = UInt32 +/// Index type for data segments within a module public typealias DataIndex = UInt32 -public typealias LocalIndex = UInt32 -public typealias LabelIndex = UInt32 +/// Index type for labels within a function +typealias LocalIndex = UInt32 +/// Index type for labels within a function +typealias LabelIndex = UInt32 + +// MARK: - Module Entities +/// An executable function representation in a module /// > Note: /// struct GuestFunction { @@ -80,7 +94,7 @@ struct GuestFunction { } public let type: TypeIndex - public let defaultLocals: UnsafeBufferPointer + let defaultLocals: UnsafeBufferPointer private var _bodyStorage: InstructionSequence? = nil private let materializer: () throws -> InstructionSequence var body: InstructionSequence { @@ -97,26 +111,28 @@ struct GuestFunction { /// > Note: /// -public struct Table: Equatable { +struct Table: Equatable { public let type: TableType } /// > Note: /// -public struct Memory: Equatable { +struct Memory: Equatable { public let type: MemoryType } +/// Global entry in a module /// > Note: /// -public struct Global: Equatable { +struct Global: Equatable { let type: GlobalType let initializer: Expression } +/// Segment of elements that are initialized in a table /// > Note: /// -public struct ElementSegment: Equatable { +struct ElementSegment: Equatable { struct Flag: OptionSet { let rawValue: UInt32 @@ -144,14 +160,15 @@ public struct ElementSegment: Equatable { case passive } - public let type: ReferenceType + let type: ReferenceType let initializer: [Expression] let mode: Mode } +/// Data segment in a module /// > Note: /// -public enum DataSegment: Equatable { +enum DataSegment: Equatable { public struct Active: Equatable { let index: MemoryIndex let offset: Expression @@ -162,31 +179,48 @@ public enum DataSegment: Equatable { case active(Active) } +/// Exported entity in a module /// > Note: /// public struct Export: Equatable { + /// Name of the export public let name: String + /// Descriptor of the export public let descriptor: ExportDescriptor } +/// Export descriptor public enum ExportDescriptor: Equatable { + /// Function export case function(FunctionIndex) + /// Table export case table(TableIndex) + /// Memory export case memory(MemoryIndex) + /// Global export case global(GlobalIndex) } +/// Import entity in a module /// > Note: /// public struct Import: Equatable { + /// Module name imported from public let module: String + /// Name of the import public let name: String + /// Descriptor of the import public let descriptor: ImportDescriptor } +/// Import descriptor public enum ImportDescriptor: Equatable { + /// Function import case function(TypeIndex) + /// Table import case table(TableType) + /// Memory import case memory(MemoryType) + /// Global import case global(GlobalType) }