Skip to content

Cleanup WasmParser module #77

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 7, 2024
4 changes: 4 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ let package = Package(
name: "WasmKitTests",
dependencies: ["WasmKit"]
),
.testTarget(
name: "WasmParserTests",
dependencies: ["WasmParser"]
),
.testTarget(
name: "WASITests",
dependencies: ["WASI"]
Expand Down
2 changes: 1 addition & 1 deletion Sources/Spectest/TestCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ extension Array where Element == Value {

extension Swift.Error {
var text: String {
if let error = self as? LegacyWasmParserError {
if let error = self as? WasmParserError {
switch error {
case .invalidMagicNumber:
return "magic header not detected"
Expand Down
1 change: 1 addition & 0 deletions Sources/WASI/WASI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import SwiftShims // For swift_stdlib_random
import SystemExtras
import SystemPackage
import WasmKit
import WasmParser

protocol WASI {
/// Reads command-line argument data.
Expand Down
4 changes: 3 additions & 1 deletion Sources/WasmKit/Execution/Instructions/Expression.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import WasmParser

/// See spec's
/// [definition](https://webassembly.github.io/spec/core/text/instructions.html?highlight=pseudo#control-instructions).
/// > The `block`, `loop` and `if` instructions are structured instructions. They bracket nested sequences of
Expand Down Expand Up @@ -54,4 +56,4 @@ struct ExpressionRef: Equatable {
/// > Note:
/// <https://webassembly.github.io/spec/core/syntax/instructions.html#expressions>

typealias Expression = [Instruction]
typealias Expression = [WasmParser.Instruction]
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import struct WasmParser.MemArg
import enum WasmParser.BlockType
import WasmParser

extension Instruction {
typealias Memarg = MemArg
Expand All @@ -22,7 +21,7 @@ extension Instruction {
case let .funcType(typeIndex):
let typeIndex = Int(typeIndex)
guard typeIndex < typeSection.count else {
throw LegacyWasmParserError.invalidTypeSectionReference
throw WasmParserError.invalidTypeSectionReference
}
let funcType = typeSection[typeIndex]
self = Instruction.BlockType(
Expand Down
30 changes: 13 additions & 17 deletions Sources/WasmKit/Execution/Instructions/Numeric.swift
Original file line number Diff line number Diff line change
Expand Up @@ -284,38 +284,34 @@ extension NumericInstruction {
_ value1: Value,
_ value2: Value
) throws -> Value {
guard case let .numeric(type) = value1.type else {
fatalError()
}

switch (self, type) {
case (.divS, _):
switch self {
case .divS:
guard !value2.isZero else { throw Trap.integerDividedByZero }
return try Value.divisionSigned(value1, value2)
case (.divU, _):
case .divU:
guard !value2.isZero else { throw Trap.integerDividedByZero }
return try Value.divisionUnsigned(value1, value2)
case (.remS, _):
case .remS:
guard !value2.isZero else { throw Trap.integerDividedByZero }
return try Value.remainderSigned(value1, value2)
case (.remU, _):
case .remU:
guard !value2.isZero else { throw Trap.integerDividedByZero }
return try Value.remainderUnsigned(value1, value2)
case (.and, _):
case .and:
return value1 & value2
case (.or, _):
case .or:
return value1 | value2
case (.xor, _):
case .xor:
return value1 ^ value2
case (.shl, _):
case .shl:
return value1 << value2
case (.shrS, _):
case .shrS:
return Value.rightShiftSigned(value1, value2)
case (.shrU, _):
case .shrU:
return Value.rightShiftUnsigned(value1, value2)
case (.rotl, _):
case .rotl:
return value1.rotl(value2)
case (.rotr, _):
case .rotr:
return value1.rotr(value2)
}
}
Expand Down
2 changes: 2 additions & 0 deletions Sources/WasmKit/Execution/Runtime/Function.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import WasmParser

/// A WebAssembly guest function or host function
public struct Function: Equatable {
internal let address: FunctionAddress
Expand Down
6 changes: 5 additions & 1 deletion Sources/WasmKit/Execution/Runtime/NameRegistry.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import struct WasmParser.NameSectionParser
import struct WasmParser.CustomSection
import class WasmParser.StaticByteStream

struct NameRegistry {
private var functionNames: [FunctionAddress: String] = [:]
private var materializers: [(inout NameRegistry) throws -> Void] = []
Expand All @@ -6,7 +10,7 @@ struct NameRegistry {

mutating func register(instance: ModuleInstance, nameSection: CustomSection) throws {
materializers.append { registry in
let stream = LegacyStaticByteStream(bytes: Array(nameSection.bytes))
let stream = StaticByteStream(bytes: Array(nameSection.bytes))
let parser = NameSectionParser(stream: stream)
for result in try parser.parseAll() {
switch result {
Expand Down
46 changes: 43 additions & 3 deletions Sources/WasmKit/Execution/Runtime/Runtime.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,22 @@ extension Runtime {
let elementIndex = UInt32(elementIndex)
switch element.mode {
case let .active(tableIndex, offsetExpression):
let initIseq = InstructionSequence(instructions: offsetExpression + [
var instructions: [Instruction] = []
switch offsetExpression.first {
case .i32Const(let value):
instructions.append(.numericConst(.i32(UInt32(bitPattern: value))))
case .globalGet(let index):
instructions.append(.globalGet(index: index))
default:
throw InstantiationError.unsupported("init expr in element section \(offsetExpression)")
}
instructions.append(contentsOf: [
.numericConst(.i32(0)),
.numericConst(.i32(UInt32(element.initializer.count))),
.tableInit(tableIndex, elementIndex),
.tableElementDrop(elementIndex),
])
let initIseq = InstructionSequence(instructions: instructions)
defer { initIseq.deallocate() }
try evaluateConstExpr(initIseq, instance: instance)

Expand All @@ -101,7 +111,18 @@ extension Runtime {
do {
for case let (dataIndex, .active(data)) in module.data.enumerated() {
assert(data.index == 0)
let iseq = InstructionSequence(instructions: data.offset + [
var instructions: [Instruction] = []
switch data.offset.first {
case .i32Const(let value):
instructions.append(.numericConst(.i32(UInt32(bitPattern: value))))
case .i64Const(let value):
instructions.append(.numericConst(.i64(UInt64(bitPattern: value))))
case .globalGet(let index):
instructions.append(.globalGet(index: index))
default:
throw InstantiationError.unsupported("init expr in data section \(data.offset)")
}
let iseq = InstructionSequence(instructions: instructions + [
.numericConst(.i32(0)),
.numericConst(.i32(UInt32(data.initializer.count))),
.memoryInit(UInt32(dataIndex)),
Expand Down Expand Up @@ -149,7 +170,26 @@ extension Runtime {
}

let globalInitializers = try module.globals.map { global in
let iseq = InstructionSequence(instructions: global.initializer)
var instructions: [Instruction] = []
switch global.initializer.first {
case .i32Const(let value):
instructions.append(.numericConst(.i32(UInt32(bitPattern: value))))
case .i64Const(let value):
instructions.append(.numericConst(.i64(UInt64(bitPattern: value))))
case .f32Const(let value):
instructions.append(.numericConst(.f32(value.bitPattern)))
case .f64Const(let value):
instructions.append(.numericConst(.f64(value.bitPattern)))
case .refNull(let type):
instructions.append(.refNull(type))
case .refFunc(let functionIndex):
instructions.append(.refFunc(functionIndex))
case .globalGet(let globalIndex):
instructions.append(.globalGet(index: globalIndex))
default:
throw InstantiationError.unsupported("init expr in global section \(global.initializer)")
}
let iseq = InstructionSequence(instructions: instructions)
defer { iseq.deallocate() }
return try evaluateConstExpr(iseq, instance: globalModuleInstance, arity: 1) { _, stack in
return stack.popValue()
Expand Down
2 changes: 2 additions & 0 deletions Sources/WasmKit/Execution/Runtime/Store.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import WasmParser

/// > Note:
/// <https://webassembly.github.io/spec/core/exec/runtime.html#addresses>
public typealias FunctionAddress = Int
Expand Down
7 changes: 6 additions & 1 deletion Sources/WasmKit/Execution/Types/Errors.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import WasmParser

public enum Trap: Error {
// FIXME: for debugging purposes, to be eventually deleted
case _raw(String)
Expand All @@ -8,7 +10,7 @@ public enum Trap: Error {
/// Stack overflow
case stackOverflow
/// The stack value type does not match the expected type
case stackValueTypesMismatch(expected: ValueType, actual: ValueType)
case stackValueTypesMismatch(expected: WasmParser.ValueType, actual: WasmParser.ValueType)
/// Too deep call stack
case callStackExhausted

Expand Down Expand Up @@ -72,6 +74,7 @@ public enum InstantiationError: Error {
case invalidTableExpression
case outOfBoundsTableAccess
case outOfBoundsMemoryAccess
case unsupported(String)

/// Human-readable text representation of the trap that `.wast` text format expects in assertions
public var assertionText: String {
Expand All @@ -80,6 +83,8 @@ public enum InstantiationError: Error {
return "out of bounds table access"
case .outOfBoundsMemoryAccess:
return "out of bounds memory access"
case .unsupported(let message):
return "unsupported operation: \(message)"
default:
return String(describing: self)
}
Expand Down
2 changes: 2 additions & 0 deletions Sources/WasmKit/Execution/Types/Instances.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import WasmParser

/// A stateful runtime representation of a ``Module``.
/// Usually instantiated by ``Runtime/instantiate(module:name:)``.
/// > Note:
Expand Down
Loading