1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
|
/// A unit of stateless WebAssembly code, which is a direct representation of a module file. You can get one
/// by calling either ``parseWasm(bytes:features:)`` or ``parseWasm(filePath:features:)``.
/// > Note:
/// <https://webassembly.github.io/spec/core/syntax/modules.html#modules>
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?
public internal(set) var imports: [Import]
public internal(set) var exports: [Export]
public internal(set) var customSections = [CustomSection]()
init(
types: [FunctionType] = [],
functions: [GuestFunction] = [],
tables: [Table] = [],
memories: [Memory] = [],
globals: [Global] = [],
elements: [ElementSegment] = [],
data: [DataSegment] = [],
start: FunctionIndex? = nil,
imports: [Import] = [],
exports: [Export] = []
) {
self.types = types
self.functions = functions
self.tables = tables
self.memories = memories
self.globals = globals
self.elements = elements
self.data = data
self.start = start
self.imports = imports
self.exports = exports
}
/// Materialize lazily-computed elements in this module
public mutating func materializeAll() throws {
for functionIndex in functions.indices {
_ = try functions[functionIndex].body
}
}
}
public struct CustomSection: Equatable {
public let name: String
public let bytes: ArraySlice<UInt8>
}
/// > Note:
/// <https://webassembly.github.io/spec/core/syntax/modules.html#syntax-typeidx>
public typealias TypeIndex = UInt32
public typealias FunctionIndex = UInt32
public typealias TableIndex = UInt32
public typealias MemoryIndex = UInt32
public typealias GlobalIndex = UInt32
public typealias ElementIndex = UInt32
public typealias DataIndex = UInt32
public typealias LocalIndex = UInt32
public typealias LabelIndex = UInt32
/// > Note:
/// <https://webassembly.github.io/spec/core/syntax/modules.html#functions>
struct GuestFunction {
init(type: TypeIndex, locals: [ValueType], body: @escaping () throws -> InstructionSequence) {
self.type = type
// TODO: Deallocate const default locals after the module is deallocated
let defaultLocals = UnsafeMutableBufferPointer<Value>.allocate(capacity: locals.count)
for (index, localType) in locals.enumerated() {
defaultLocals[index] = localType.defaultValue
}
self.defaultLocals = UnsafeBufferPointer(defaultLocals)
self.materializer = body
}
public let type: TypeIndex
public let defaultLocals: UnsafeBufferPointer<Value>
private var _bodyStorage: InstructionSequence? = nil
private let materializer: () throws -> InstructionSequence
var body: InstructionSequence {
mutating get throws {
if let materialized = _bodyStorage {
return materialized
}
let result = try materializer()
self._bodyStorage = result
return result
}
}
}
/// > Note:
/// <https://webassembly.github.io/spec/core/syntax/modules.html#tables>
public struct Table: Equatable {
public let type: TableType
}
/// > Note:
/// <https://webassembly.github.io/spec/core/syntax/modules.html#memories>
public struct Memory: Equatable {
public let type: MemoryType
}
/// > Note:
/// <https://webassembly.github.io/spec/core/syntax/modules.html#globals>
public struct Global: Equatable {
let type: GlobalType
let initializer: Expression
}
/// > Note:
/// <https://webassembly.github.io/spec/core/syntax/modules.html#element-segments>
public struct ElementSegment: Equatable {
struct Flag: OptionSet {
let rawValue: UInt32
init(rawValue: UInt32) {
self.rawValue = rawValue
}
var segmentHasElemKind: Bool {
!contains(.usesExpressions) && rawValue != 0
}
var segmentHasRefType: Bool {
contains(.usesExpressions) && rawValue != 4
}
static let isPassiveOrDeclarative = Flag(rawValue: 1 << 0)
static let isDeclarative = Flag(rawValue: 1 << 1)
static let hasTableIndex = Flag(rawValue: 1 << 1)
static let usesExpressions = Flag(rawValue: 1 << 2)
}
enum Mode: Equatable {
case active(table: TableIndex, offset: Expression)
case declarative
case passive
}
public let type: ReferenceType
let initializer: [Expression]
let mode: Mode
}
/// > Note:
/// <https://webassembly.github.io/spec/core/syntax/modules.html#data-segments>
public enum DataSegment: Equatable {
public struct Active: Equatable {
let index: MemoryIndex
let offset: Expression
let initializer: ArraySlice<UInt8>
}
case passive([UInt8])
case active(Active)
}
/// > Note:
/// <https://webassembly.github.io/spec/core/syntax/modules.html#exports>
public struct Export: Equatable {
public let name: String
public let descriptor: ExportDescriptor
}
public enum ExportDescriptor: Equatable {
case function(FunctionIndex)
case table(TableIndex)
case memory(MemoryIndex)
case global(GlobalIndex)
}
/// > Note:
/// <https://webassembly.github.io/spec/core/syntax/modules.html#imports>
public struct Import: Equatable {
public let module: String
public let name: String
public let descriptor: ImportDescriptor
}
public enum ImportDescriptor: Equatable {
case function(TypeIndex)
case table(TableType)
case memory(MemoryType)
case global(GlobalType)
}
|