File: Module.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (192 lines) | stat: -rw-r--r-- 6,012 bytes parent folder | download
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)
}