Skip to content

Commit 8eac109

Browse files
Add documentation in InstructionSupport.swift
1 parent 52a7d69 commit 8eac109

File tree

4 files changed

+98
-122
lines changed

4 files changed

+98
-122
lines changed

Sources/WasmKit/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ add_wasmkit_library(WasmKit
1010
Component/ComponentTypes.swift
1111
Execution/Instructions/Reference.swift
1212
Execution/Instructions/Control.swift
13-
Execution/Instructions/Expression.swift
1413
Execution/Instructions/Instruction.swift
1514
Execution/Instructions/Parametric.swift
1615
Execution/Instructions/Table.swift

Sources/WasmKit/Execution/Function.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,30 @@ struct WasmFunctionEntity {
202202

203203
typealias InternalUncompiledCode = EntityHandle<Code>
204204

205+
/// A compiled instruction sequence.
206+
struct InstructionSequence: Equatable {
207+
let instructions: UnsafeMutableBufferPointer<CodeSlot>
208+
/// The maximum height of the value stack during execution of this function.
209+
/// This height does not count the locals.
210+
let maxStackHeight: Int
211+
212+
let constants: UnsafeBufferPointer<UntypedValue>
213+
214+
init(instructions: UnsafeMutableBufferPointer<CodeSlot>, maxStackHeight: Int, constants: UnsafeBufferPointer<UntypedValue>) {
215+
self.instructions = instructions
216+
self.maxStackHeight = maxStackHeight
217+
self.constants = constants
218+
}
219+
220+
var baseAddress: UnsafeMutablePointer<CodeSlot> {
221+
self.instructions.baseAddress!
222+
}
223+
224+
static func == (lhs: InstructionSequence, rhs: InstructionSequence) -> Bool {
225+
lhs.instructions.baseAddress == rhs.instructions.baseAddress
226+
}
227+
}
228+
205229
enum CodeBody {
206230
case uncompiled(InternalUncompiledCode)
207231
case compiled(InstructionSequence)

Sources/WasmKit/Execution/Instructions/Expression.swift

Lines changed: 0 additions & 47 deletions
This file was deleted.

Sources/WasmKit/Execution/Instructions/InstructionSupport.swift

Lines changed: 74 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -44,92 +44,35 @@ struct LLVReg: Equatable, ShiftedVReg {
4444
}
4545
}
4646

47-
extension RawUnsignedInteger {
48-
init(_ slot: CodeSlot, shiftWidth: Int) {
49-
let mask = CodeSlot(Self.max)
50-
let bitPattern = (slot >> shiftWidth) & mask
51-
self = Self(bitPattern)
52-
}
53-
54-
func bits(shiftWidth: Int) -> CodeSlot {
55-
CodeSlot(self) << shiftWidth
56-
}
57-
}
58-
59-
extension RawSignedInteger {
60-
init(_ slot: CodeSlot, shiftWidth: Int) {
61-
self.init(bitPattern: Unsigned(slot, shiftWidth: shiftWidth))
62-
}
63-
64-
func bits(shiftWidth: Int) -> CodeSlot {
65-
Unsigned(bitPattern: self).bits(shiftWidth: shiftWidth)
66-
}
67-
}
68-
69-
extension UntypedValue {
70-
init(_ slot: CodeSlot, shiftWidth: Int) {
71-
self.init(storage: slot)
72-
}
73-
74-
func bits(shiftWidth: Int) -> CodeSlot { storage }
75-
}
47+
// MARK: - Immediate load/emit support
7648

49+
/// A protocol that represents an immediate associated with an instruction.
7750
protocol InstructionImmediate {
51+
/// Loads an immediate from the instruction sequence.
52+
///
53+
/// - Parameter pc: The program counter to read from.
54+
/// - Returns: The loaded immediate.
7855
static func load(from pc: inout Pc) -> Self
56+
57+
/// Emits the layout of the immediate to be emitted.
58+
///
59+
/// - Parameter emitSlot: The closure to schedule a slot emission.
60+
/// This closure receives a builder closure that builds the slot.
61+
///
62+
/// - Note: This method is intended to work at meta-level to allow
63+
/// knowing the size of slots without actual immediate values.
7964
static func emit(to emitSlot: @escaping ((Self) -> CodeSlot) -> Void)
8065
}
8166

8267
extension InstructionImmediate {
68+
/// Emits the immediate value
69+
///
70+
/// - Parameter emitSlot: The closure to emit a slot.
8371
func emit(to emitSlot: @escaping (CodeSlot) -> Void) {
8472
Self.emit { buildCodeSlot in
8573
emitSlot(buildCodeSlot(self))
8674
}
8775
}
88-
static func emit<Parent>(to emitParent: @escaping ((Parent) -> CodeSlot) -> Void, _ child: KeyPath<Parent, Self>) {
89-
Self.emit { emitChild in
90-
emitParent { emitChild($0[keyPath: child]) }
91-
}
92-
}
93-
}
94-
95-
extension InstructionImmediate {
96-
static func load(from pc: inout Pc) -> Self {
97-
pc.read()
98-
}
99-
static func emit(to emitSlot: ((Self) -> CodeSlot) -> Void) {
100-
assert(MemoryLayout<Self>.size == 8)
101-
emitSlot { unsafeBitCast($0, to: CodeSlot.self) }
102-
}
103-
}
104-
105-
extension VReg: InstructionImmediate {
106-
static func load(from pc: inout Pc) -> Self {
107-
VReg(bitPattern: UInt16(pc.read(UInt64.self)))
108-
}
109-
static func emit(to emitSlot: @escaping ((Self) -> CodeSlot) -> Void) {
110-
emitSlot { CodeSlot(UInt16(bitPattern: $0)) }
111-
}
112-
113-
typealias Slot2 = (VReg, VReg, pad: UInt32)
114-
static func load2(from pc: inout Pc) -> (Self, Self) {
115-
let (x, y, _) = pc.read(Slot2.self)
116-
return (x, y)
117-
}
118-
static func emit2(to emitSlot: @escaping ((Self, Self) -> CodeSlot) -> Void) {
119-
emitSlot { x, y in
120-
let slot: Slot2 = (x, y, 0)
121-
return unsafeBitCast(slot, to: CodeSlot.self)
122-
}
123-
}
124-
}
125-
126-
extension LLVReg: InstructionImmediate {
127-
static func load(from pc: inout Pc) -> Self {
128-
Self(storage: Int64(bitPattern: pc.read()))
129-
}
130-
static func emit(to emitSlot: ((Self) -> CodeSlot) -> Void) {
131-
emitSlot { UInt64(bitPattern: $0.value) }
132-
}
13376
}
13477

13578
extension UInt32: InstructionImmediate {
@@ -150,6 +93,8 @@ extension Int32: InstructionImmediate {
15093
}
15194
}
15295

96+
// MARK: - Immediate type extensions
97+
15398
extension Instruction.RefNullOperand {
15499
init(result: VReg, type: ReferenceType) {
155100
self.init(result: result, rawType: type.rawValue)
@@ -210,9 +155,64 @@ extension Instruction {
210155
typealias OnExitOperand = FunctionIndex
211156
}
212157

158+
extension RawUnsignedInteger {
159+
init(_ slot: CodeSlot, shiftWidth: Int) {
160+
let mask = CodeSlot(Self.max)
161+
let bitPattern = (slot >> shiftWidth) & mask
162+
self = Self(bitPattern)
163+
}
164+
165+
func bits(shiftWidth: Int) -> CodeSlot {
166+
CodeSlot(self) << shiftWidth
167+
}
168+
}
169+
170+
extension RawSignedInteger {
171+
init(_ slot: CodeSlot, shiftWidth: Int) {
172+
self.init(bitPattern: Unsigned(slot, shiftWidth: shiftWidth))
173+
}
174+
175+
func bits(shiftWidth: Int) -> CodeSlot {
176+
Unsigned(bitPattern: self).bits(shiftWidth: shiftWidth)
177+
}
178+
}
179+
180+
extension UntypedValue {
181+
init(_ slot: CodeSlot, shiftWidth: Int) {
182+
self.init(storage: slot)
183+
}
184+
185+
func bits(shiftWidth: Int) -> CodeSlot { storage }
186+
}
187+
213188
/// The type of an opcode identifier.
214189
typealias OpcodeID = UInt64
215190

191+
// MARK: - Instruction printing support
192+
193+
extension InstructionSequence {
194+
func write<Target>(to target: inout Target, context: inout InstructionPrintingContext) where Target : TextOutputStream {
195+
var hexOffsetWidth = String(instructions.count - 1, radix: 16).count
196+
hexOffsetWidth = (hexOffsetWidth + 1) & ~1
197+
198+
guard let cursorStart = instructions.baseAddress else { return }
199+
let cursorEnd = cursorStart.advanced(by: instructions.count)
200+
201+
var cursor = cursorStart
202+
while cursor < cursorEnd {
203+
let index = cursor - cursorStart
204+
var hexOffset = String(index, radix: 16)
205+
while hexOffset.count < hexOffsetWidth {
206+
hexOffset = "0" + hexOffset
207+
}
208+
target.write("0x\(hexOffset): ")
209+
let instruction = Instruction.load(from: &cursor)
210+
context.print(instruction: instruction, to: &target)
211+
target.write("\n")
212+
}
213+
}
214+
}
215+
216216
struct InstructionPrintingContext {
217217
let shouldColor: Bool
218218
let function: Function

0 commit comments

Comments
 (0)