diff --git a/Sources/WasmKit/Execution/Function.swift b/Sources/WasmKit/Execution/Function.swift index 3786cf16..a2d57d86 100644 --- a/Sources/WasmKit/Execution/Function.swift +++ b/Sources/WasmKit/Execution/Function.swift @@ -253,19 +253,18 @@ struct WasmFunctionEntity { let store = store.value let engine = store.engine let type = self.type - var translator = try InstructionTranslator( - allocator: store.allocator.iseqAllocator, - engineConfiguration: engine.configuration, - funcTypeInterner: engine.funcTypeInterner, - module: instance, - type: engine.resolveType(type), - locals: code.locals, - functionIndex: index, - codeSize: code.expression.count, - isIntercepting: engine.interceptor != nil - ) let iseq = try code.withValue { code in - try translator.translate(code: code) + try InstructionTranslator( + allocator: store.allocator.iseqAllocator, + engineConfiguration: engine.configuration, + funcTypeInterner: engine.funcTypeInterner, + module: instance, + type: engine.resolveType(type), + locals: code.locals, + functionIndex: index, + codeSize: code.expression.count, + isIntercepting: engine.interceptor != nil + ).translate(code: code) } self.code = .compiled(iseq) return iseq diff --git a/Sources/WasmKit/Translator.swift b/Sources/WasmKit/Translator.swift index 6f3e1116..b7544472 100644 --- a/Sources/WasmKit/Translator.swift +++ b/Sources/WasmKit/Translator.swift @@ -293,7 +293,7 @@ struct StackLayout { } } -struct InstructionTranslator: InstructionVisitor { +struct InstructionTranslator: ~Copyable, InstructionVisitor { typealias Output = Void typealias LabelRef = Int @@ -526,15 +526,15 @@ struct InstructionTranslator: InstructionVisitor { } } - fileprivate struct ISeqBuilder { + fileprivate struct ISeqBuilder: ~Copyable { typealias InstructionFactoryWithLabel = ( - ISeqBuilder, + borrowing ISeqBuilder, // The position of the next slot of the creating instruction _ source: MetaProgramCounter, // The position of the resolved label _ target: MetaProgramCounter ) -> (WasmKit.Instruction) - typealias BrTableEntryFactory = (ISeqBuilder, MetaProgramCounter) -> Instruction.BrTableOperand.Entry + typealias BrTableEntryFactory = (borrowing ISeqBuilder, MetaProgramCounter) -> Instruction.BrTableOperand.Entry typealias BuildingBrTable = UnsafeMutableBufferPointer enum OnPinAction { @@ -639,7 +639,7 @@ struct InstructionTranslator: InstructionVisitor { } } - func finalize() -> [UInt64] { + consuming func finalize() -> [UInt64] { return instructions } @@ -707,7 +707,7 @@ struct InstructionTranslator: InstructionVisitor { line: UInt = #line, make: @escaping ( - ISeqBuilder, + borrowing ISeqBuilder, // The position of the next slot of the creating instruction _ source: MetaProgramCounter, // The position of the resolved label @@ -1077,7 +1077,7 @@ struct InstructionTranslator: InstructionVisitor { try valueStack.truncate(height: currentFrame.stackHeight) } - private mutating func finalize() throws -> InstructionSequence { + private consuming func finalize() throws -> InstructionSequence { if controlStack.numberOfFrames > 1 { throw ValidationError(.expectedMoreEndInstructions(count: controlStack.numberOfFrames - 1)) } @@ -1102,7 +1102,7 @@ struct InstructionTranslator: InstructionVisitor { // MARK: Main entry point /// Translate a Wasm expression into a sequence of instructions. - mutating func translate(code: Code) throws -> InstructionSequence { + consuming func translate(code: Code) throws -> InstructionSequence { if isIntercepting { // Emit `onEnter` instruction at the beginning of the function emit(.onEnter(functionIndex)) diff --git a/Sources/WasmParser/BinaryInstructionDecoder.swift b/Sources/WasmParser/BinaryInstructionDecoder.swift index 5cc84908..cc1337af 100644 --- a/Sources/WasmParser/BinaryInstructionDecoder.swift +++ b/Sources/WasmParser/BinaryInstructionDecoder.swift @@ -90,7 +90,10 @@ protocol BinaryInstructionDecoder { } @inlinable -func parseBinaryInstruction(visitor: inout some InstructionVisitor, decoder: inout some BinaryInstructionDecoder) throws -> Bool { +func parseBinaryInstruction( + visitor: inout some InstructionVisitor & ~Copyable, + decoder: inout some BinaryInstructionDecoder +) throws -> Bool { let opcode0 = try decoder.claimNextByte() switch opcode0 { case 0x00: diff --git a/Sources/WasmParser/InstructionVisitor.swift b/Sources/WasmParser/InstructionVisitor.swift index 2a6b0271..cd7d9fb6 100644 --- a/Sources/WasmParser/InstructionVisitor.swift +++ b/Sources/WasmParser/InstructionVisitor.swift @@ -309,7 +309,7 @@ extension AnyInstructionVisitor { /// /// The visitor pattern is used while parsing WebAssembly expressions to allow for easy extensibility. /// See the expression parsing method ``Code/parseExpression(visitor:)`` -public protocol InstructionVisitor { +public protocol InstructionVisitor: ~Copyable { /// Visiting `unreachable` instruction. mutating func visitUnreachable() throws /// Visiting `nop` instruction. @@ -420,7 +420,7 @@ public protocol InstructionVisitor { mutating func visitUnknown(_ opcode: [UInt8]) throws -> Bool } -extension InstructionVisitor { +extension InstructionVisitor where Self: ~Copyable { /// Visits an instruction. public mutating func visit(_ instruction: Instruction) throws { switch instruction { @@ -482,7 +482,7 @@ extension InstructionVisitor { } // MARK: - Placeholder implementations -extension InstructionVisitor { +extension InstructionVisitor where Self: ~Copyable { public mutating func visitUnreachable() throws {} public mutating func visitNop() throws {} public mutating func visitBlock(blockType: BlockType) throws {} diff --git a/Sources/WasmParser/WasmParser.swift b/Sources/WasmParser/WasmParser.swift index 0bca6049..791b0712 100644 --- a/Sources/WasmParser/WasmParser.swift +++ b/Sources/WasmParser/WasmParser.swift @@ -160,7 +160,7 @@ public struct ExpressionParser { } @inlinable - public mutating func visit(visitor: inout V) throws -> Bool { + public mutating func visit(visitor: inout some InstructionVisitor & ~Copyable) throws -> Bool { isLastEnd = try parser.parseInstruction(visitor: &visitor) let shouldContinue = try !parser.stream.hasReachedEnd() if !shouldContinue { @@ -751,7 +751,7 @@ extension Parser: BinaryInstructionDecoder { /// Returns: `true` if the parsed instruction is the block end instruction. @inline(__always) @inlinable - mutating func parseInstruction(visitor v: inout V) throws -> Bool { + mutating func parseInstruction(visitor v: inout some InstructionVisitor & ~Copyable) throws -> Bool { return try parseBinaryInstruction(visitor: &v, decoder: &self) } diff --git a/Utilities/Sources/WasmGen.swift b/Utilities/Sources/WasmGen.swift index af354614..a1addda2 100644 --- a/Utilities/Sources/WasmGen.swift +++ b/Utilities/Sources/WasmGen.swift @@ -95,7 +95,7 @@ enum WasmGen { /// /// The visitor pattern is used while parsing WebAssembly expressions to allow for easy extensibility. /// See the expression parsing method ``Code/parseExpression(visitor:)`` - public protocol InstructionVisitor { + public protocol InstructionVisitor: ~Copyable { """ for instruction in instructions.categorized { @@ -118,7 +118,7 @@ enum WasmGen { code += """ - extension InstructionVisitor { + extension InstructionVisitor where Self: ~Copyable { /// Visits an instruction. public mutating func visit(_ instruction: Instruction) throws { switch instruction { @@ -150,7 +150,7 @@ enum WasmGen { code += """ // MARK: - Placeholder implementations - extension InstructionVisitor { + extension InstructionVisitor where Self: ~Copyable { """ for instruction in instructions.categorized { @@ -561,7 +561,10 @@ enum WasmGen { code += """ @inlinable - func parseBinaryInstruction(visitor: inout some InstructionVisitor, decoder: inout some BinaryInstructionDecoder) throws -> Bool { + func parseBinaryInstruction( + visitor: inout some InstructionVisitor & ~Copyable, + decoder: inout some BinaryInstructionDecoder + ) throws -> Bool { """ func renderSwitchCase(_ root: Trie, depth: Int = 0) {