porffor 0.0.0-650350

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,272 @@
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: 0xffffffffffff8
19
+ };
20
+
21
+ // todo: turn these into built-ins once arrays and these become less hacky
22
+
23
+ export const PrototypeFuncs = function() {
24
+ const noUnlikelyChecks = process.argv.includes('-funsafe-no-unlikely-proto-checks');
25
+
26
+ this[TYPES._array] = {
27
+ // lX = local accessor of X ({ get, set }), iX = local index of X, wX = wasm ops of X
28
+ // todo: out of bounds (>) properly
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
+ // todo: out of bounds properly
151
+ at: (pointer, length, wIndex, iTmp, arrayShell) => {
152
+ const [ newOut, newPointer ] = arrayShell(1, 'i16');
153
+
154
+ return [
155
+ // setup new/out array
156
+ ...newOut,
157
+ [ Opcodes.drop ],
158
+
159
+ ...number(0, Valtype.i32), // base 0 for store later
160
+ Opcodes.i32_to_u,
161
+
162
+ ...wIndex,
163
+ [ Opcodes.local_tee, iTmp ],
164
+
165
+ // if index < 0: access index + array length
166
+ ...number(0, Valtype.i32),
167
+ [ Opcodes.i32_lt_s ],
168
+ [ Opcodes.if, Blocktype.void ],
169
+ [ Opcodes.local_get, iTmp ],
170
+ ...length.cachedI32,
171
+ [ Opcodes.i32_add ],
172
+ [ Opcodes.local_set, iTmp ],
173
+ [ Opcodes.end ],
174
+
175
+ // if still < 0 or >= length: return undefined
176
+ [ Opcodes.local_get, iTmp ],
177
+ ...number(0, Valtype.i32),
178
+ [ Opcodes.i32_lt_s ],
179
+
180
+ [ Opcodes.local_get, iTmp ],
181
+ ...length.cachedI32,
182
+ [ Opcodes.i32_ge_s ],
183
+ [ Opcodes.i32_or ],
184
+
185
+ [ Opcodes.if, Blocktype.void ],
186
+ ...number(UNDEFINED),
187
+ [ Opcodes.br, 1 ],
188
+ [ Opcodes.end ],
189
+
190
+ [ Opcodes.local_get, iTmp ],
191
+ ...number(ValtypeSize.i16, Valtype.i32),
192
+ [ Opcodes.i32_mul ],
193
+
194
+ // load current string ind {arg}
195
+ [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32) ],
196
+
197
+ // store to new string ind 0
198
+ [ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
199
+
200
+ // return new string (pointer)
201
+ ...number(newPointer)
202
+ ];
203
+ },
204
+
205
+ // todo: out of bounds properly
206
+ charAt: (pointer, length, wIndex, _, arrayShell) => {
207
+ const [ newOut, newPointer ] = arrayShell(1, 'i16');
208
+
209
+ return [
210
+ // setup new/out array
211
+ ...newOut,
212
+ [ Opcodes.drop ],
213
+
214
+ ...number(0, Valtype.i32), // base 0 for store later
215
+
216
+ ...wIndex,
217
+
218
+ Opcodes.i32_to,
219
+ ...number(ValtypeSize.i16, Valtype.i32),
220
+ [ Opcodes.i32_mul ],
221
+
222
+ // load current string ind {arg}
223
+ [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32) ],
224
+
225
+ // store to new string ind 0
226
+ [ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
227
+
228
+ // return new string (page)
229
+ ...number(newPointer)
230
+ ];
231
+ },
232
+
233
+ charCodeAt: (pointer, length, wIndex, iTmp) => {
234
+ return [
235
+ ...wIndex,
236
+ Opcodes.i32_to,
237
+ [ Opcodes.local_set, iTmp ],
238
+
239
+ // index < 0
240
+ ...(noUnlikelyChecks ? [] : [
241
+ [ Opcodes.local_get, iTmp ],
242
+ ...number(0, Valtype.i32),
243
+ [ Opcodes.i32_lt_s ],
244
+ ]),
245
+
246
+ // index >= length
247
+ [ Opcodes.local_get, iTmp ],
248
+ ...length.cachedI32,
249
+ [ Opcodes.i32_ge_s ],
250
+
251
+ ...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
252
+ [ Opcodes.if, Blocktype.void ],
253
+ ...number(NaN),
254
+ [ Opcodes.br, 1 ],
255
+ [ Opcodes.end ],
256
+
257
+ [ Opcodes.local_get, iTmp ],
258
+ ...number(ValtypeSize.i16, Valtype.i32),
259
+ [ Opcodes.i32_mul ],
260
+
261
+ // load current string ind {arg}
262
+ [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32) ],
263
+ Opcodes.i32_from_u
264
+ ];
265
+ },
266
+ };
267
+
268
+ this[TYPES.string].at.local = valtypeBinary;
269
+ this[TYPES.string].at.returnType = TYPES.string;
270
+ this[TYPES.string].charAt.returnType = TYPES.string;
271
+ this[TYPES.string].charCodeAt.local = Valtype.i32;
272
+ };
@@ -0,0 +1,154 @@
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
+ export default (funcs, globals, tags, pages, flags) => {
12
+ const types = [], typeCache = {};
13
+
14
+ const optLevel = parseInt(process.argv.find(x => x.startsWith('-O'))?.[2] ?? 1);
15
+
16
+ const getType = (params, returns) => {
17
+ const hash = `${params.join(',')}_${returns.join(',')}`;
18
+ if (optLog) log('sections', `getType(${JSON.stringify(params)}, ${JSON.stringify(returns)}) -> ${hash} | cache: ${typeCache[hash]}`);
19
+ if (optLevel >= 1 && typeCache[hash] !== undefined) return typeCache[hash];
20
+
21
+ const type = [ FuncType, ...encodeVector(params), ...encodeVector(returns) ];
22
+ const idx = types.length;
23
+
24
+ types.push(type);
25
+
26
+ return typeCache[hash] = idx;
27
+ };
28
+
29
+ let importFuncs = [];
30
+
31
+ if (optLevel < 1) {
32
+ importFuncs = importedFuncs;
33
+ } else {
34
+ let imports = new Map();
35
+
36
+ // tree shake imports
37
+ for (const f of funcs) {
38
+ for (const inst of f.wasm) {
39
+ if (inst[0] === Opcodes.call && inst[1] < importedFuncs.length) {
40
+ const idx = inst[1];
41
+ const func = importedFuncs[idx];
42
+
43
+ if (!imports.has(func.name)) imports.set(func.name, { ...func, idx: imports.size });
44
+ inst[1] = imports.get(func.name).idx;
45
+ }
46
+ }
47
+ }
48
+
49
+ importFuncs = [...imports.values()];
50
+
51
+ // fix call indexes for non-imports
52
+ const delta = importedFuncs.length - importFuncs.length;
53
+ for (const f of funcs) {
54
+ f.index -= delta;
55
+
56
+ for (const inst of f.wasm) {
57
+ if (inst[0] === Opcodes.call && inst[1] >= importedFuncs.length) {
58
+ inst[1] -= delta;
59
+ }
60
+ }
61
+ }
62
+ }
63
+
64
+ if (optLog) log('sections', `treeshake: using ${importFuncs.length}/${importedFuncs.length} imports`);
65
+
66
+ const importSection = importFuncs.length === 0 ? [] : createSection(
67
+ Section.import,
68
+ encodeVector(importFuncs.map(x => [ 0, ...encodeString(x.import), ExportDesc.func, getType(new Array(x.params).fill(valtypeBinary), new Array(x.returns).fill(valtypeBinary)) ]))
69
+ );
70
+
71
+ const funcSection = createSection(
72
+ Section.func,
73
+ encodeVector(funcs.map(x => getType(x.params, x.returns))) // type indexes
74
+ );
75
+
76
+ const globalSection = Object.keys(globals).length === 0 ? [] : createSection(
77
+ Section.global,
78
+ encodeVector(Object.keys(globals).map(x => [ globals[x].type, 0x01, ...number(globals[x].init ?? 0, globals[x].type).flat(), Opcodes.end ]))
79
+ );
80
+
81
+ const exports = funcs.filter(x => x.export).map((x, i) => [ ...encodeString(x.name === 'main' ? 'm' : x.name), ExportDesc.func, x.index ]);
82
+
83
+ const usesMemory = pages.size > 0;
84
+ const memorySection = !usesMemory ? [] : createSection(
85
+ Section.memory,
86
+ encodeVector([ [ 0x00, Math.ceil((pages.size * pageSize) / PageSize) ] ])
87
+ );
88
+
89
+ // export memory if used
90
+ if (usesMemory) exports.unshift([ ...encodeString('$'), ExportDesc.mem, 0x00 ]);
91
+
92
+ const tagSection = tags.length === 0 ? [] : createSection(
93
+ Section.tag,
94
+ encodeVector(tags.map(x => [ 0x00, getType(x.params, x.results) ]))
95
+ );
96
+
97
+ // export first tag if used
98
+ if (tags.length !== 0) exports.unshift([ ...encodeString('0'), ExportDesc.tag, 0x00 ]);
99
+
100
+ const exportSection = createSection(
101
+ Section.export,
102
+ encodeVector(exports)
103
+ );
104
+
105
+ const codeSection = createSection(
106
+ Section.code,
107
+ encodeVector(funcs.map(x => {
108
+ const locals = Object.values(x.locals).sort((a, b) => a.idx - b.idx).slice(x.params.length).sort((a, b) => a.idx - b.idx);
109
+
110
+ let localDecl = [], typeCount = 0, lastType;
111
+ for (let i = 0; i < locals.length; i++) {
112
+ const local = locals[i];
113
+ if (i !== 0 && local.type !== lastType) {
114
+ localDecl.push(encodeLocal(typeCount, lastType));
115
+ typeCount = 0;
116
+ }
117
+
118
+ typeCount++;
119
+ lastType = local.type;
120
+ }
121
+
122
+ if (typeCount !== 0) localDecl.push(encodeLocal(typeCount, lastType));
123
+
124
+ return encodeVector([ ...encodeVector(localDecl), ...x.wasm.flat().filter(x => x !== null), Opcodes.end ]);
125
+ }))
126
+ );
127
+
128
+ const typeSection = createSection(
129
+ Section.type,
130
+ encodeVector(types)
131
+ );
132
+
133
+ if (process.argv.includes('-sections')) console.log({
134
+ typeSection: typeSection.map(x => x.toString(16)),
135
+ importSection: importSection.map(x => x.toString(16)),
136
+ funcSection: funcSection.map(x => x.toString(16)),
137
+ globalSection: globalSection.map(x => x.toString(16)),
138
+ exportSection: exportSection.map(x => x.toString(16)),
139
+ codeSection: codeSection.map(x => x.toString(16))
140
+ });
141
+
142
+ return Uint8Array.from([
143
+ ...Magic,
144
+ ...ModuleVersion,
145
+ ...typeSection,
146
+ ...importSection,
147
+ ...funcSection,
148
+ ...memorySection,
149
+ ...tagSection,
150
+ ...globalSection,
151
+ ...exportSection,
152
+ ...codeSection
153
+ ]);
154
+ };
@@ -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
+ };