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.
- package/LICENSE +21 -0
- package/README.md +275 -0
- package/compiler/builtins/base64.js +92 -0
- package/compiler/builtins.js +770 -0
- package/compiler/codeGen.js +2027 -0
- package/compiler/decompile.js +102 -0
- package/compiler/embedding.js +19 -0
- package/compiler/encoding.js +217 -0
- package/compiler/expression.js +70 -0
- package/compiler/index.js +67 -0
- package/compiler/opt.js +436 -0
- package/compiler/parse.js +8 -0
- package/compiler/prototype.js +272 -0
- package/compiler/sections.js +154 -0
- package/compiler/wasmSpec.js +200 -0
- package/compiler/wrap.js +119 -0
- package/package.json +23 -0
- package/porf.cmd +2 -0
- package/publish.js +13 -0
- package/runner/compare.js +35 -0
- package/runner/index.js +34 -0
- package/runner/info.js +54 -0
- package/runner/profile.js +47 -0
- package/runner/repl.js +104 -0
- package/runner/sizes.js +38 -0
- package/runner/transform.js +36 -0
- package/sw.js +26 -0
- package/util/enum.js +20 -0
@@ -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
|
+
};
|