porffor 0.0.0-05f898f

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,271 @@
1
+ import { Opcodes, Blocktype, Valtype, ValtypeSize, PageSize } from "./wasmSpec.js";
2
+ import { number } from "./embedding.js";
3
+ import { unsignedLEB128 } from "./encoding.js";
4
+ import { UNDEFINED } from "./builtins.js";
5
+
6
+ // todo: do not duplicate this
7
+ const TYPES = {
8
+ number: 0xffffffffffff0,
9
+ boolean: 0xffffffffffff1,
10
+ string: 0xffffffffffff2,
11
+ undefined: 0xffffffffffff3,
12
+ object: 0xffffffffffff4,
13
+ function: 0xffffffffffff5,
14
+ symbol: 0xffffffffffff6,
15
+ bigint: 0xffffffffffff7,
16
+
17
+ // these are not "typeof" types but tracked internally
18
+ _array: 0xfffffffffff0f,
19
+ _regexp: 0xfffffffffff1f
20
+ };
21
+
22
+ // todo: turn these into built-ins once arrays and these become less hacky
23
+
24
+ export const PrototypeFuncs = function() {
25
+ const noUnlikelyChecks = process.argv.includes('-funsafe-no-unlikely-proto-checks');
26
+
27
+ this[TYPES._array] = {
28
+ // lX = local accessor of X ({ get, set }), iX = local index of X, wX = wasm ops of X
29
+ at: (pointer, length, wIndex, iTmp) => [
30
+ ...wIndex,
31
+ Opcodes.i32_to,
32
+ [ Opcodes.local_tee, iTmp ],
33
+
34
+ // if index < 0: access index + array length
35
+ ...number(0, Valtype.i32),
36
+ [ Opcodes.i32_lt_s ],
37
+ [ Opcodes.if, Blocktype.void ],
38
+ [ Opcodes.local_get, iTmp ],
39
+ ...length.cachedI32,
40
+ [ Opcodes.i32_add ],
41
+ [ Opcodes.local_set, iTmp ],
42
+ [ Opcodes.end ],
43
+
44
+ // if still < 0 or >= length: return undefined
45
+ [ Opcodes.local_get, iTmp ],
46
+ ...number(0, Valtype.i32),
47
+ [ Opcodes.i32_lt_s ],
48
+
49
+ [ Opcodes.local_get, iTmp ],
50
+ ...length.cachedI32,
51
+ [ Opcodes.i32_ge_s ],
52
+ [ Opcodes.i32_or ],
53
+
54
+ [ Opcodes.if, Blocktype.void ],
55
+ ...number(UNDEFINED),
56
+ [ Opcodes.br, 1 ],
57
+ [ Opcodes.end ],
58
+
59
+ [ Opcodes.local_get, iTmp ],
60
+ ...number(ValtypeSize[valtype], Valtype.i32),
61
+ [ Opcodes.i32_mul ],
62
+
63
+ // read from memory
64
+ [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32) ]
65
+ ],
66
+
67
+ // todo: only for 1 argument
68
+ push: (pointer, length, wNewMember) => [
69
+ // get memory offset of array at last index (length)
70
+ ...length.cachedI32,
71
+ ...number(ValtypeSize[valtype], Valtype.i32),
72
+ [ Opcodes.i32_mul ],
73
+
74
+ // generated wasm for new member
75
+ ...wNewMember,
76
+
77
+ // store in memory
78
+ [ Opcodes.store, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32) ],
79
+
80
+ // bump array length by 1 and return it
81
+ ...length.setI32([
82
+ ...length.cachedI32,
83
+ ...number(1, Valtype.i32),
84
+ [ Opcodes.i32_add ]
85
+ ]),
86
+
87
+ ...length.get
88
+ ],
89
+
90
+ pop: (pointer, length) => [
91
+ // if length == 0, noop
92
+ ...length.cachedI32,
93
+ [ Opcodes.i32_eqz ],
94
+ [ Opcodes.if, Blocktype.void ],
95
+ ...number(UNDEFINED),
96
+ [ Opcodes.br, 1 ],
97
+ [ Opcodes.end ],
98
+
99
+ // todo: should we store 0/undefined in "removed" element?
100
+
101
+ // decrement length by 1
102
+ ...length.setI32([
103
+ ...length.cachedI32,
104
+ ...number(1, Valtype.i32),
105
+ [ Opcodes.i32_sub ]
106
+ ]),
107
+
108
+ // load last element
109
+ ...length.cachedI32,
110
+ ...number(ValtypeSize[valtype], Valtype.i32),
111
+ [ Opcodes.i32_mul ],
112
+
113
+ [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32 - ValtypeSize[valtype]) ]
114
+ ],
115
+
116
+ shift: (pointer, length) => [
117
+ // if length == 0, noop
118
+ ...length.cachedI32,
119
+ Opcodes.i32_eqz,
120
+ [ Opcodes.if, Blocktype.void ],
121
+ ...number(UNDEFINED),
122
+ [ Opcodes.br, 1 ],
123
+ [ Opcodes.end ],
124
+
125
+ // todo: should we store 0/undefined in "removed" element?
126
+
127
+ // decrement length by 1
128
+ ...length.setI32([
129
+ ...length.cachedI32,
130
+ ...number(1, Valtype.i32),
131
+ [ Opcodes.i32_sub ]
132
+ ]),
133
+
134
+ // load first element
135
+ ...number(0, Valtype.i32),
136
+ [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32) ],
137
+
138
+ // offset all elements by -1 ind
139
+ ...number(pointer + ValtypeSize.i32, Valtype.i32), // dst = base array index + length size
140
+ ...number(pointer + ValtypeSize.i32 + ValtypeSize[valtype], Valtype.i32), // src = base array index + length size + an index
141
+ ...number(pageSize - ValtypeSize.i32 - ValtypeSize[valtype], Valtype.i32), // size = PageSize - length size - an index
142
+ [ ...Opcodes.memory_copy, 0x00, 0x00 ]
143
+ ]
144
+ };
145
+
146
+ this[TYPES._array].at.local = Valtype.i32;
147
+ this[TYPES._array].push.noArgRetLength = true;
148
+
149
+ this[TYPES.string] = {
150
+ at: (pointer, length, wIndex, iTmp, arrayShell) => {
151
+ const [ newOut, newPointer ] = arrayShell(1, 'i16');
152
+
153
+ return [
154
+ // setup new/out array
155
+ ...newOut,
156
+ [ Opcodes.drop ],
157
+
158
+ ...number(0, Valtype.i32), // base 0 for store later
159
+
160
+ ...wIndex,
161
+ Opcodes.i32_to_u,
162
+ [ Opcodes.local_tee, iTmp ],
163
+
164
+ // if index < 0: access index + array length
165
+ ...number(0, Valtype.i32),
166
+ [ Opcodes.i32_lt_s ],
167
+ [ Opcodes.if, Blocktype.void ],
168
+ [ Opcodes.local_get, iTmp ],
169
+ ...length.cachedI32,
170
+ [ Opcodes.i32_add ],
171
+ [ Opcodes.local_set, iTmp ],
172
+ [ Opcodes.end ],
173
+
174
+ // if still < 0 or >= length: return undefined
175
+ [ Opcodes.local_get, iTmp ],
176
+ ...number(0, Valtype.i32),
177
+ [ Opcodes.i32_lt_s ],
178
+
179
+ [ Opcodes.local_get, iTmp ],
180
+ ...length.cachedI32,
181
+ [ Opcodes.i32_ge_s ],
182
+ [ Opcodes.i32_or ],
183
+
184
+ [ Opcodes.if, Blocktype.void ],
185
+ ...number(UNDEFINED),
186
+ [ Opcodes.br, 1 ],
187
+ [ Opcodes.end ],
188
+
189
+ [ Opcodes.local_get, iTmp ],
190
+ ...number(ValtypeSize.i16, Valtype.i32),
191
+ [ Opcodes.i32_mul ],
192
+
193
+ // load current string ind {arg}
194
+ [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32) ],
195
+
196
+ // store to new string ind 0
197
+ [ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
198
+
199
+ // return new string (pointer)
200
+ ...number(newPointer)
201
+ ];
202
+ },
203
+
204
+ // todo: out of bounds properly
205
+ charAt: (pointer, length, wIndex, _, arrayShell) => {
206
+ const [ newOut, newPointer ] = arrayShell(1, 'i16');
207
+
208
+ return [
209
+ // setup new/out array
210
+ ...newOut,
211
+ [ Opcodes.drop ],
212
+
213
+ ...number(0, Valtype.i32), // base 0 for store later
214
+
215
+ ...wIndex,
216
+
217
+ Opcodes.i32_to,
218
+ ...number(ValtypeSize.i16, Valtype.i32),
219
+ [ Opcodes.i32_mul ],
220
+
221
+ // load current string ind {arg}
222
+ [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32) ],
223
+
224
+ // store to new string ind 0
225
+ [ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
226
+
227
+ // return new string (page)
228
+ ...number(newPointer)
229
+ ];
230
+ },
231
+
232
+ charCodeAt: (pointer, length, wIndex, iTmp) => {
233
+ return [
234
+ ...wIndex,
235
+ Opcodes.i32_to,
236
+ [ Opcodes.local_set, iTmp ],
237
+
238
+ // index < 0
239
+ ...(noUnlikelyChecks ? [] : [
240
+ [ Opcodes.local_get, iTmp ],
241
+ ...number(0, Valtype.i32),
242
+ [ Opcodes.i32_lt_s ],
243
+ ]),
244
+
245
+ // index >= length
246
+ [ Opcodes.local_get, iTmp ],
247
+ ...length.cachedI32,
248
+ [ Opcodes.i32_ge_s ],
249
+
250
+ ...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
251
+ [ Opcodes.if, Blocktype.void ],
252
+ ...number(NaN),
253
+ [ Opcodes.br, 1 ],
254
+ [ Opcodes.end ],
255
+
256
+ [ Opcodes.local_get, iTmp ],
257
+ ...number(ValtypeSize.i16, Valtype.i32),
258
+ [ Opcodes.i32_mul ],
259
+
260
+ // load current string ind {arg}
261
+ [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32) ],
262
+ Opcodes.i32_from_u
263
+ ];
264
+ },
265
+ };
266
+
267
+ this[TYPES.string].at.local = Valtype.i32;
268
+ this[TYPES.string].at.returnType = TYPES.string;
269
+ this[TYPES.string].charAt.returnType = TYPES.string;
270
+ this[TYPES.string].charCodeAt.local = Valtype.i32;
271
+ };
@@ -0,0 +1,180 @@
1
+ import { Valtype, FuncType, Empty, ExportDesc, Section, Magic, ModuleVersion, Opcodes, PageSize } from './wasmSpec.js';
2
+ import { encodeVector, encodeString, encodeLocal } from './encoding.js';
3
+ import { number } from './embedding.js';
4
+ import { importedFuncs } from './builtins.js';
5
+
6
+ const createSection = (type, data) => [
7
+ type,
8
+ ...encodeVector(data)
9
+ ];
10
+
11
+ const customSection = (name, data) => [
12
+ Section.custom,
13
+ ...encodeVector([...encodeString(name), ...data])
14
+ ];
15
+
16
+ const chHint = (topTier, baselineTier, strategy) => {
17
+ // 1 byte of 4 2 bit components: spare, top tier, baseline tier, compilation strategy
18
+ // tiers: 0x00 = default, 0x01 = baseline (liftoff), 0x02 = optimized (turbofan)
19
+ // strategy: 0x00 = default, 0x01 = lazy, 0x02 = eager, 0x03 = lazy baseline, eager top tier
20
+ return (strategy | (baselineTier << 2) | (topTier << 4));
21
+ };
22
+
23
+ export default (funcs, globals, tags, pages, flags) => {
24
+ const types = [], typeCache = {};
25
+
26
+ const optLevel = parseInt(process.argv.find(x => x.startsWith('-O'))?.[2] ?? 1);
27
+
28
+ const compileHints = process.argv.includes('-compile-hints');
29
+ if (compileHints) log('sections', 'warning: compile hints is V8 only w/ experimental arg! (you used -compile-hints)');
30
+
31
+ const getType = (params, returns) => {
32
+ const hash = `${params.join(',')}_${returns.join(',')}`;
33
+ if (optLog) log('sections', `getType(${JSON.stringify(params)}, ${JSON.stringify(returns)}) -> ${hash} | cache: ${typeCache[hash]}`);
34
+ if (optLevel >= 1 && typeCache[hash] !== undefined) return typeCache[hash];
35
+
36
+ const type = [ FuncType, ...encodeVector(params), ...encodeVector(returns) ];
37
+ const idx = types.length;
38
+
39
+ types.push(type);
40
+
41
+ return typeCache[hash] = idx;
42
+ };
43
+
44
+ let importFuncs = [];
45
+
46
+ if (optLevel < 1) {
47
+ importFuncs = importedFuncs;
48
+ } else {
49
+ let imports = new Map();
50
+
51
+ // tree shake imports
52
+ for (const f of funcs) {
53
+ for (const inst of f.wasm) {
54
+ if ((inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) && inst[1] < importedFuncs.length) {
55
+ const idx = inst[1];
56
+ const func = importedFuncs[idx];
57
+
58
+ if (!imports.has(func.name)) imports.set(func.name, { ...func, idx: imports.size });
59
+ inst[1] = imports.get(func.name).idx;
60
+ }
61
+ }
62
+ }
63
+
64
+ importFuncs = [...imports.values()];
65
+
66
+ // fix call indexes for non-imports
67
+ const delta = importedFuncs.length - importFuncs.length;
68
+ for (const f of funcs) {
69
+ f.originalIndex = f.index;
70
+ f.index -= delta;
71
+
72
+ for (const inst of f.wasm) {
73
+ if ((inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) && inst[1] >= importedFuncs.length) {
74
+ inst[1] -= delta;
75
+ }
76
+ }
77
+ }
78
+ }
79
+ globalThis.importFuncs = importFuncs;
80
+
81
+ if (optLog) log('sections', `treeshake: using ${importFuncs.length}/${importedFuncs.length} imports`);
82
+
83
+ const importSection = importFuncs.length === 0 ? [] : createSection(
84
+ Section.import,
85
+ encodeVector(importFuncs.map(x => [ 0, ...encodeString(x.import), ExportDesc.func, getType(new Array(x.params).fill(valtypeBinary), new Array(x.returns).fill(valtypeBinary)) ]))
86
+ );
87
+
88
+ const funcSection = createSection(
89
+ Section.func,
90
+ encodeVector(funcs.map(x => getType(x.params, x.returns))) // type indexes
91
+ );
92
+
93
+ // compilation hints section - unspec v8 only
94
+ // https://github.com/WebAssembly/design/issues/1473#issuecomment-1431274746
95
+ const chSection = !compileHints ? [] : customSection(
96
+ 'compilationHints',
97
+ // for now just do everything as optimise eager
98
+ encodeVector(funcs.map(_ => chHint(0x02, 0x02, 0x02)))
99
+ );
100
+
101
+ const globalSection = Object.keys(globals).length === 0 ? [] : createSection(
102
+ Section.global,
103
+ encodeVector(Object.keys(globals).map(x => [ globals[x].type, 0x01, ...number(globals[x].init ?? 0, globals[x].type).flat(), Opcodes.end ]))
104
+ );
105
+
106
+ const exports = funcs.filter(x => x.export).map((x, i) => [ ...encodeString(x.name === 'main' ? 'm' : x.name), ExportDesc.func, x.index ]);
107
+
108
+ const usesMemory = pages.size > 0;
109
+ const memorySection = !usesMemory ? [] : createSection(
110
+ Section.memory,
111
+ encodeVector([ [ 0x00, Math.ceil((pages.size * pageSize) / PageSize) ] ])
112
+ );
113
+
114
+ // export memory if used
115
+ if (usesMemory) exports.unshift([ ...encodeString('$'), ExportDesc.mem, 0x00 ]);
116
+
117
+ const tagSection = tags.length === 0 ? [] : createSection(
118
+ Section.tag,
119
+ encodeVector(tags.map(x => [ 0x00, getType(x.params, x.results) ]))
120
+ );
121
+
122
+ // export first tag if used
123
+ if (tags.length !== 0) exports.unshift([ ...encodeString('0'), ExportDesc.tag, 0x00 ]);
124
+
125
+ const exportSection = createSection(
126
+ Section.export,
127
+ encodeVector(exports)
128
+ );
129
+
130
+ const codeSection = createSection(
131
+ Section.code,
132
+ encodeVector(funcs.map(x => {
133
+ const locals = Object.values(x.locals).sort((a, b) => a.idx - b.idx).slice(x.params.length).sort((a, b) => a.idx - b.idx);
134
+
135
+ let localDecl = [], typeCount = 0, lastType;
136
+ for (let i = 0; i < locals.length; i++) {
137
+ const local = locals[i];
138
+ if (i !== 0 && local.type !== lastType) {
139
+ localDecl.push(encodeLocal(typeCount, lastType));
140
+ typeCount = 0;
141
+ }
142
+
143
+ typeCount++;
144
+ lastType = local.type;
145
+ }
146
+
147
+ if (typeCount !== 0) localDecl.push(encodeLocal(typeCount, lastType));
148
+
149
+ return encodeVector([ ...encodeVector(localDecl), ...x.wasm.flat().filter(x => x !== null), Opcodes.end ]);
150
+ }))
151
+ );
152
+
153
+ const typeSection = createSection(
154
+ Section.type,
155
+ encodeVector(types)
156
+ );
157
+
158
+ if (process.argv.includes('-sections')) console.log({
159
+ typeSection: typeSection.map(x => x.toString(16)),
160
+ importSection: importSection.map(x => x.toString(16)),
161
+ funcSection: funcSection.map(x => x.toString(16)),
162
+ globalSection: globalSection.map(x => x.toString(16)),
163
+ exportSection: exportSection.map(x => x.toString(16)),
164
+ codeSection: codeSection.map(x => x.toString(16))
165
+ });
166
+
167
+ return Uint8Array.from([
168
+ ...Magic,
169
+ ...ModuleVersion,
170
+ ...typeSection,
171
+ ...importSection,
172
+ ...funcSection,
173
+ ...chSection,
174
+ ...memorySection,
175
+ ...tagSection,
176
+ ...globalSection,
177
+ ...exportSection,
178
+ ...codeSection
179
+ ]);
180
+ };
@@ -0,0 +1,200 @@
1
+ import { enumify } from "../util/enum.js";
2
+
3
+ export const Section = enumify('custom', 'type', 'import', 'func', 'table', 'memory', 'global', 'export', 'start', 'element', 'code', 'data', 'data_count', 'tag');
4
+ export const ExportDesc = enumify('func', 'table', 'mem', 'global', 'tag');
5
+
6
+ export const Mut = enumify('const', 'var');
7
+
8
+ export const Valtype = {
9
+ i32: 0x7f,
10
+ i64: 0x7e,
11
+ f64: 0x7c,
12
+ v128: 0x7b
13
+ };
14
+
15
+ export const Blocktype = {
16
+ void: 0x40,
17
+ };
18
+
19
+ export const Opcodes = {
20
+ unreachable: 0x00,
21
+ nop: 0x01,
22
+
23
+ block: 0x02,
24
+ loop: 0x03,
25
+ if: 0x04,
26
+ else: 0x05,
27
+
28
+ try: 0x06,
29
+ catch: 0x07,
30
+ catch_all: 0x19,
31
+ delegate: 0x18,
32
+ throw: 0x08,
33
+ rethrow: 0x09,
34
+
35
+ return: 0x0F,
36
+
37
+ call: 0x10,
38
+ call_indirect: 0x11,
39
+ return_call: 0x12,
40
+ return_call_indirect: 0x13,
41
+
42
+ end: 0x0b,
43
+ br: 0x0c,
44
+ br_if: 0x0d,
45
+ call: 0x10,
46
+ drop: 0x1a,
47
+
48
+ local_get: 0x20,
49
+ local_set: 0x21,
50
+ local_tee: 0x22, // set and return value (set and get combined)
51
+
52
+ global_get: 0x23,
53
+ global_set: 0x24,
54
+
55
+ i32_load: 0x28,
56
+ i64_load: 0x29,
57
+ f64_load: 0x2b,
58
+
59
+ i32_load16_s: 0x2e,
60
+ i32_load16_u: 0x2f,
61
+
62
+ i32_store16: 0x3b,
63
+
64
+ i32_store: 0x36,
65
+ i64_store: 0x37,
66
+ f64_store: 0x39,
67
+
68
+ memory_grow: 0x40,
69
+
70
+ i32_const: 0x41,
71
+ i64_const: 0x42,
72
+ f64_const: 0x44,
73
+
74
+ i32_eqz: 0x45,
75
+ i32_eq: 0x46,
76
+ i32_ne: 0x47,
77
+
78
+ i32_lt_s: 0x48,
79
+ i32_le_s: 0x4c,
80
+ i32_gt_s: 0x4a,
81
+ i32_ge_s: 0x4e,
82
+
83
+ i32_clz: 0x67,
84
+ i32_ctz: 0x68,
85
+ i32_popcnt: 0x69,
86
+
87
+ i32_add: 0x6a,
88
+ i32_sub: 0x6b,
89
+ i32_mul: 0x6c,
90
+ i32_div_s: 0x6d,
91
+ i32_rem_s: 0x6f,
92
+
93
+ i32_and: 0x71,
94
+ i32_or: 0x72,
95
+ i32_xor: 0x73,
96
+ i32_shl: 0x74,
97
+ i32_shr_s: 0x75,
98
+ i32_shr_u: 0x76,
99
+
100
+ i64_eqz: 0x50,
101
+ i64_eq: 0x51,
102
+ i64_ne: 0x52,
103
+
104
+ i64_lt_s: 0x53,
105
+ i64_le_s: 0x57,
106
+ i64_gt_s: 0x55,
107
+ i64_ge_s: 0x59,
108
+
109
+ i64_add: 0x7c,
110
+ i64_sub: 0x7d,
111
+ i64_mul: 0x7e,
112
+ i64_div_s: 0x7f,
113
+ i64_rem_s: 0x81,
114
+
115
+ i64_and: 0x83,
116
+ i64_or: 0x84,
117
+ i64_xor: 0x85,
118
+ i64_shl: 0x86,
119
+ i64_shr_s: 0x87,
120
+ i64_shr_u: 0x88,
121
+
122
+ f64_eq: 0x61,
123
+ f64_ne: 0x62,
124
+
125
+ f64_lt: 0x63,
126
+ f64_le: 0x65,
127
+ f64_gt: 0x64,
128
+ f64_ge: 0x66,
129
+
130
+ f64_abs: 0x99,
131
+ f64_neg: 0x9a,
132
+
133
+ f64_ceil: 0x9b,
134
+ f64_floor: 0x9c,
135
+ f64_trunc: 0x9d,
136
+ f64_nearest: 0x9e,
137
+
138
+ f64_sqrt: 0x9f,
139
+ f64_add: 0xa0,
140
+ f64_sub: 0xa1,
141
+ f64_mul: 0xa2,
142
+ f64_div: 0xa3,
143
+ f64_min: 0xa4,
144
+ f64_max: 0xa5,
145
+ f64_copysign: 0xa6,
146
+
147
+ i32_wrap_i64: 0xa7,
148
+ i64_extend_i32_s: 0xac,
149
+ i64_extend_i32_u: 0xad,
150
+
151
+ f32_demote_f64: 0xb6,
152
+ f64_promote_f32: 0xbb,
153
+
154
+ f64_convert_i32_s: 0xb7,
155
+ f64_convert_i32_u: 0xb8,
156
+ f64_convert_i64_s: 0xb9,
157
+ f64_convert_i64_u: 0xba,
158
+
159
+ i32_trunc_sat_f64_s: [ 0xfc, 0x02 ],
160
+ i32_trunc_sat_f64_u: [ 0xfc, 0x03 ],
161
+
162
+ memory_copy: [ 0xfc, 0x0a ],
163
+
164
+ // simd insts are 0xFD simdop: varuint32
165
+ v128_load: [ 0xfd, 0x00 ],
166
+ v128_const: [ 0xfd, 0x0c ],
167
+
168
+ i8x16_shuffle: [ 0xfd, 0x0d ],
169
+
170
+ i32x4_splat: [ 0xfd, 0x11 ],
171
+ i32x4_extract_lane: [ 0xfd, 0x1b ],
172
+ i32x4_replace_lane: [ 0xfd, 0x1c ],
173
+
174
+ i16x8_extract_lane: [ 0xfd, 0x18 ], // _s
175
+ i16x8_replace_lane: [ 0xfd, 0x1a ],
176
+
177
+ i32x4_add: [ 0xfd, 0xae, 0x01 ],
178
+ i32x4_sub: [ 0xfd, 0xb1, 0x01 ],
179
+ i32x4_mul: [ 0xfd, 0xb5, 0x01 ],
180
+
181
+ i32x4_dot_i16x8_s: [ 0xfd, 0xba, 0x01 ],
182
+ };
183
+
184
+ export const FuncType = 0x60;
185
+ export const Empty = 0x00;
186
+
187
+ export const Magic = [0x00, 0x61, 0x73, 0x6d];
188
+ export const ModuleVersion = [0x01, 0x00, 0x00, 0x00];
189
+
190
+ export const PageSize = 65536; // 64KiB (1024 * 8)
191
+
192
+ export const ValtypeSize = {
193
+ i32: 4,
194
+ i64: 8,
195
+ f64: 8,
196
+
197
+ // special
198
+ i8: 1,
199
+ i16: 2
200
+ };