porffor 0.58.14 → 0.58.16

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.
@@ -16,614 +16,650 @@ const f64ToI32Op = {
16
16
  [Opcodes.f64_div]: Opcodes.i32_div_s,
17
17
  };
18
18
 
19
+ // const inv = (obj, keyMap = x => x) => Object.keys(obj).reduce((acc, x) => { acc[keyMap(obj[x])] = x; return acc; }, {});
20
+ // const invOpcodes = inv(Opcodes);
21
+
19
22
  export default ({ name, wasm, locals: _locals, params }) => {
20
23
  let locals = Object.values(_locals);
24
+ const localNames = Object.keys(_locals);
21
25
  const localValtypes = locals.map(x => x.type);
26
+ const localNeeded = new Array(locals.length).fill(0);
22
27
 
23
- const resetLocals = () => {
24
- locals = new Array(locals.length).fill(false);
25
- };
26
- resetLocals();
27
-
28
- let stack = []; // "stack"
29
- for (let i = 0; i < wasm.length; i++) {
30
- let op = wasm[i];
31
- if (!op) continue;
28
+ // every pass does the same initial low level things
29
+ // each subsequent pass does it again and does more high-level things
30
+ const passes = [
31
+ 0, // initial (simplify/reduce, mark locals)
32
+ 1 // local deletion
33
+ ];
32
34
 
33
- op = [ ...op ];
34
- wasm[i] = op;
35
+ while (passes.length > 0) {
36
+ const pass = passes.shift();
35
37
 
36
- let opcode = op[0];
37
- if (opcode === 0xfc) { // multibyte op
38
- opcode = (opcode << 8) + op[1];
39
- }
38
+ let stack = []; // "stack"
39
+ const empty = () => {
40
+ stack = [];
41
+ };
40
42
 
41
- const push = val => {
42
- stack.push({ val, op });
43
+ const reset = () => {
44
+ locals = new Array(locals.length).fill(false);
45
+ empty();
43
46
  };
44
47
 
45
- const peek = () => stack[stack.length - 1]?.val;
46
- const popWithoutRemove = () => stack.pop().val;
48
+ reset();
49
+
50
+ for (let i = 0; i < wasm.length; i++) {
51
+ let op = wasm[i];
52
+ if (!op) continue;
53
+
54
+ op = [ ...op ];
55
+ wasm[i] = op;
56
+
57
+ let opcode = op[0];
58
+ if (opcode === 0xfc) { // multibyte op
59
+ opcode = (opcode << 8) + op[1];
60
+ }
61
+
62
+ const push = val => {
63
+ stack.push({ val, op });
64
+ };
65
+
66
+ const peek = () => stack[stack.length - 1]?.val;
67
+ const popWithoutRemove = () => stack.pop().val;
68
+
69
+ const pop = () => {
70
+ const popped = stack.pop();
71
+
72
+ // remove the op
73
+ wasm.splice(wasm.indexOf(popped.op), 1);
74
+ i--;
75
+
76
+ return popped.val;
77
+ };
78
+ const pop2 = () => [ pop(), pop() ];
79
+
80
+ const bool = v => v ? 1 : 0;
81
+
82
+ const replaceOp = newOp => op.splice(0, op.length, ...newOp);
83
+ const replaceVal = (val, valtype) => replaceOp(number(val, valtype));
84
+
85
+ // debugging
86
+ // if (Prefs.f === name) console.log(invOpcodes[opcode], stack);
87
+ switch (opcode) {
88
+ case Opcodes.if: {
89
+ if (stack.length < 1) { empty(); break; }
90
+ const cond = bool(pop());
91
+
92
+ // find else split and end
93
+ let j = i + 1;
94
+ let depth = 0, elseStart = 0;
95
+ for (; j < wasm.length; j++) {
96
+ const op = wasm[j][0];
97
+ if (op === Opcodes.if || op === Opcodes.block || op === Opcodes.loop || op === Opcodes.try) depth++;
98
+ if (op === Opcodes.else && depth === 0) elseStart = j;
99
+ if (op === Opcodes.end) {
100
+ depth--;
101
+ if (depth < 0) break;
102
+ }
103
+ if (op === Opcodes.br || op === Opcodes.br_if) wasm[j][1] -= 1;
104
+ }
105
+
106
+ if (cond) {
107
+ // remove else if it exists, or just remove end
108
+ if (elseStart) wasm.splice(elseStart, j - elseStart + 1);
109
+ else wasm.splice(j, 1);
110
+ } else {
111
+ // remove truthy conseq and keep else if it exists, or just remove entire thing
112
+ if (elseStart) {
113
+ wasm.splice(j, 1); // remove end
114
+ wasm.splice(i + 1, elseStart - i + 1); // remove truthy conseq
115
+ } else wasm.splice(i + 1, j - i + 0); // no else, remove entire if
116
+ }
117
+
118
+ // remove this if op
119
+ wasm.splice(i, 1);
120
+ i--;
47
121
 
48
- // let debugPops = [];
49
- const pop = () => {
50
- const popped = stack.pop();
51
- // debugPops.unshift({ ...popped, index: wasm.indexOf(popped.op) });
122
+ break;
123
+ }
52
124
 
53
- // remove the op
54
- wasm.splice(wasm.indexOf(popped.op), 1);
55
- i--;
125
+ case Opcodes.i32_const: {
126
+ const n = read_signedLEB128(op.slice(1));
127
+ push(n);
128
+ break;
129
+ }
130
+ case Opcodes.f64_const: {
131
+ const n = op[1];
132
+ push(n);
133
+ break;
134
+ }
56
135
 
57
- return popped.val;
58
- };
59
- const pop2 = () => [ pop(), pop() ];
136
+ case Opcodes.i32_eqz: {
137
+ if (stack.length < 1) { empty(); break; };
138
+ const v = bool(pop() === 0);
60
139
 
61
- const bool = v => v ? 1 : 0;
140
+ replaceVal(v, Valtype.i32);
141
+ push(v);
142
+ break;
143
+ }
144
+ case Opcodes.i32_eq: {
145
+ if (stack.length < 2) { empty(); break; };
146
+ const [ b, a ] = pop2();
147
+ const v = bool(a === b);
62
148
 
63
- const replaceOp = newOp => {
64
- // console.log(`\x1b[4m${name}\x1b[0m`);
65
- // const oldOps = [ ...debugPops, { op, index: i + debugPops.length } ];
66
- // for (const x of oldOps) {
67
- // console.log(`\x1b[90m${x.index.toString().padStart(4)} ▌\x1b[0m ${disassemble([ x.op ], undefined, undefined, _locals).slice(0, -1)}${x.val != null ? ` \x1b[2m(${x.val})\x1b[0m` : ''}`);
68
- // }
69
- // process.stdout.write(`\x1b[s\x1b[${oldOps.length}A\x1b[40C\x1b[2m->\x1b[0m ${disassemble([ newOp ]).slice(0, -1)}\x1b[u\n`);
149
+ replaceVal(v, Valtype.i32);
150
+ push(v);
151
+ break;
152
+ }
153
+ case Opcodes.i32_ne: {
154
+ if (stack.length < 2) { empty(); break; };
155
+ const [ b, a ] = pop2();
156
+ const v = bool(a !== b);
70
157
 
71
- op.splice(0, op.length, ...newOp);
72
- };
73
- const replaceVal = (val, valtype) => replaceOp(number(val, valtype));
158
+ replaceVal(v, Valtype.i32);
159
+ push(v);
160
+ break;
161
+ }
162
+ case Opcodes.i32_lt_s: {
163
+ if (stack.length < 2) { empty(); break; };
164
+ const [ b, a ] = pop2();
165
+ const v = bool(a < b);
74
166
 
75
- const empty = () => {
76
- stack = [];
77
- };
167
+ replaceVal(v, Valtype.i32);
168
+ push(v);
169
+ break;
170
+ }
171
+ case Opcodes.i32_le_s: {
172
+ if (stack.length < 2) { empty(); break; };
173
+ const [ b, a ] = pop2();
174
+ const v = bool(a <= b);
78
175
 
79
- switch (opcode) {
80
- // case Opcodes.if: {
81
- // if (stack.length < 1) { empty(); break; }
82
- // const cond = bool(pop());
83
-
84
- // // find else split and end
85
- // let j = i + 1;
86
- // let depth = 0, elseStart = 0;
87
- // for (; j < wasm.length; j++) {
88
- // const op = wasm[j][0];
89
- // if (op === Opcodes.if || op === Opcodes.block || op === Opcodes.loop || op === Opcodes.try) depth++;
90
- // if (op === Opcodes.else && depth === 0) elseStart = j;
91
- // if (op === Opcodes.end) {
92
- // depth--;
93
- // if (depth < 0) break;
94
- // }
95
- // if (op === Opcodes.br || op === Opcodes.br_if) wasm[j][1] -= 1;
96
- // }
176
+ replaceVal(v, Valtype.i32);
177
+ push(v);
178
+ break;
179
+ }
180
+ case Opcodes.i32_gt_s: {
181
+ if (stack.length < 2) { empty(); break; };
182
+ const [ b, a ] = pop2();
183
+ const v = bool(a > b);
97
184
 
98
- // if (cond) {
99
- // // remove else if it exists, or just remove end
100
- // if (elseStart) wasm.splice(elseStart, j - elseStart + 1);
101
- // else wasm.splice(j, 1);
102
- // } else {
103
- // // remove truthy conseq and keep else if it exists, or just remove entire thing
104
- // if (elseStart) {
105
- // wasm.splice(j, 1); // remove end
106
- // wasm.splice(i + 1, elseStart - i + 1); // remove truthy conseq
107
- // } else wasm.splice(i + 1, j - i + 0); // no else, remove entire if
108
- // }
185
+ replaceVal(v, Valtype.i32);
186
+ push(v);
187
+ break;
188
+ }
189
+ case Opcodes.i32_ge_s: {
190
+ if (stack.length < 2) { empty(); break; };
191
+ const [ b, a ] = pop2();
192
+ const v = bool(a >= b);
109
193
 
110
- // // remove this if op
111
- // wasm.splice(i, 1);
194
+ replaceVal(v, Valtype.i32);
195
+ push(v);
196
+ break;
197
+ }
112
198
 
113
- // break;
114
- // }
199
+ case Opcodes.i32_add: {
200
+ if (stack.length < 2) { empty(); break; };
201
+ const [ b, a ] = pop2();
202
+ const v = a + b;
115
203
 
116
- case Opcodes.i32_const: {
117
- const n = read_signedLEB128(op.slice(1));
118
- push(n);
119
- break;
120
- }
121
- case Opcodes.f64_const: {
122
- const n = op[1];
123
- push(n);
124
- break;
125
- }
204
+ replaceVal(v, Valtype.i32);
205
+ push(v);
206
+ break;
207
+ }
208
+ case Opcodes.i32_sub: {
209
+ if (stack.length < 2) { empty(); break; };
210
+ const [ b, a ] = pop2();
211
+ const v = a - b;
126
212
 
127
- case Opcodes.i32_eqz: {
128
- if (stack.length < 1) { empty(); break; };
129
- const v = bool(pop() === 0);
213
+ replaceVal(v, Valtype.i32);
214
+ push(v);
215
+ break;
216
+ }
217
+ case Opcodes.i32_mul: {
218
+ if (stack.length < 2) { empty(); break; };
219
+ const [ b, a ] = pop2();
220
+ const v = a * b;
130
221
 
131
- replaceVal(v, Valtype.i32);
132
- push(v);
133
- break;
134
- }
135
- case Opcodes.i32_eq: {
136
- if (stack.length < 2) { empty(); break; };
137
- const [ b, a ] = pop2();
138
- const v = bool(a === b);
139
-
140
- replaceVal(v, Valtype.i32);
141
- push(v);
142
- break;
143
- }
144
- case Opcodes.i32_ne: {
145
- if (stack.length < 2) { empty(); break; };
146
- const [ b, a ] = pop2();
147
- const v = bool(a !== b);
148
-
149
- replaceVal(v, Valtype.i32);
150
- push(v);
151
- break;
152
- }
153
- case Opcodes.i32_lt_s: {
154
- if (stack.length < 2) { empty(); break; };
155
- const [ b, a ] = pop2();
156
- const v = bool(a < b);
157
-
158
- replaceVal(v, Valtype.i32);
159
- push(v);
160
- break;
161
- }
162
- case Opcodes.i32_le_s: {
163
- if (stack.length < 2) { empty(); break; };
164
- const [ b, a ] = pop2();
165
- const v = bool(a <= b);
166
-
167
- replaceVal(v, Valtype.i32);
168
- push(v);
169
- break;
170
- }
171
- case Opcodes.i32_gt_s: {
172
- if (stack.length < 2) { empty(); break; };
173
- const [ b, a ] = pop2();
174
- const v = bool(a > b);
175
-
176
- replaceVal(v, Valtype.i32);
177
- push(v);
178
- break;
179
- }
180
- case Opcodes.i32_ge_s: {
181
- if (stack.length < 2) { empty(); break; };
182
- const [ b, a ] = pop2();
183
- const v = bool(a >= b);
184
-
185
- replaceVal(v, Valtype.i32);
186
- push(v);
187
- break;
188
- }
222
+ replaceVal(v, Valtype.i32);
223
+ push(v);
224
+ break;
225
+ }
226
+ case Opcodes.i32_div_s: {
227
+ if (stack.length < 2) { empty(); break; };
228
+ const [ b, a ] = pop2();
229
+ const v = a / b;
189
230
 
190
- case Opcodes.i32_add: {
191
- if (stack.length < 2) { empty(); break; };
192
- const [ b, a ] = pop2();
193
- const v = a + b;
231
+ replaceVal(v, Valtype.i32);
232
+ push(v);
233
+ break;
234
+ }
235
+ case Opcodes.i32_rem_s: {
236
+ if (stack.length < 2) { empty(); break; };
237
+ const [ b, a ] = pop2();
238
+ const v = a % b; // not rem but good enough
194
239
 
195
- replaceVal(v, Valtype.i32);
196
- push(v);
197
- break;
198
- }
199
- case Opcodes.i32_sub: {
200
- if (stack.length < 2) { empty(); break; };
201
- const [ b, a ] = pop2();
202
- const v = a - b;
203
-
204
- replaceVal(v, Valtype.i32);
205
- push(v);
206
- break;
207
- }
208
- case Opcodes.i32_mul: {
209
- if (stack.length < 2) { empty(); break; };
210
- const [ b, a ] = pop2();
211
- const v = a * b;
212
-
213
- replaceVal(v, Valtype.i32);
214
- push(v);
215
- break;
216
- }
217
- case Opcodes.i32_div_s: {
218
- if (stack.length < 2) { empty(); break; };
219
- const [ b, a ] = pop2();
220
- const v = a / b;
221
-
222
- replaceVal(v, Valtype.i32);
223
- push(v);
224
- break;
225
- }
226
- case Opcodes.i32_rem_s: {
227
- if (stack.length < 2) { empty(); break; };
228
- const [ b, a ] = pop2();
229
- const v = a % b; // not rem but good enough
230
-
231
- replaceVal(v, Valtype.i32);
232
- push(v);
233
- break;
234
- }
240
+ replaceVal(v, Valtype.i32);
241
+ push(v);
242
+ break;
243
+ }
235
244
 
236
- case Opcodes.i32_and: {
237
- if (stack.length < 2) { empty(); break; };
238
- const [ b, a ] = pop2();
239
- const v = a & b;
245
+ case Opcodes.i32_and: {
246
+ if (stack.length < 2) { empty(); break; };
247
+ const [ b, a ] = pop2();
248
+ const v = a & b;
240
249
 
241
- replaceVal(v, Valtype.i32);
242
- push(v);
243
- break;
244
- }
245
- case Opcodes.i32_or: {
246
- if (stack.length < 2) { empty(); break; };
247
- const [ b, a ] = pop2();
248
- const v = a | b;
249
-
250
- replaceVal(v, Valtype.i32);
251
- push(v);
252
- break;
253
- }
254
- case Opcodes.i32_xor: {
255
- if (stack.length < 2) { empty(); break; };
256
- const [ b, a ] = pop2();
257
- const v = a ^ b;
258
-
259
- replaceVal(v, Valtype.i32);
260
- push(v);
261
- break;
262
- }
263
- case Opcodes.i32_shl: {
264
- if (stack.length < 2) { empty(); break; };
265
- const [ b, a ] = pop2();
266
- const v = a << b;
267
-
268
- replaceVal(v, Valtype.i32);
269
- push(v);
270
- break;
271
- }
272
- case Opcodes.i32_shr_s: {
273
- if (stack.length < 2) { empty(); break; };
274
- const [ b, a ] = pop2();
275
- const v = a >> b;
276
-
277
- replaceVal(v, Valtype.i32);
278
- push(v);
279
- break;
280
- }
281
- case Opcodes.i32_shr_u: {
282
- if (stack.length < 2) { empty(); break; };
283
- const [ b, a ] = pop2();
284
- const v = a >>> b;
285
-
286
- replaceVal(v, Valtype.i32);
287
- push(v);
288
- break;
289
- }
250
+ replaceVal(v, Valtype.i32);
251
+ push(v);
252
+ break;
253
+ }
254
+ case Opcodes.i32_or: {
255
+ if (stack.length < 2) { empty(); break; };
256
+ const [ b, a ] = pop2();
257
+ const v = a | b;
290
258
 
291
- case Opcodes.f64_eq: {
292
- if (stack.length < 2) { empty(); break; };
293
- const [ b, a ] = pop2();
294
- const v = bool(a === b);
259
+ replaceVal(v, Valtype.i32);
260
+ push(v);
261
+ break;
262
+ }
263
+ case Opcodes.i32_xor: {
264
+ if (stack.length < 2) { empty(); break; };
265
+ const [ b, a ] = pop2();
266
+ const v = a ^ b;
295
267
 
296
- replaceVal(v, Valtype.i32);
297
- push(v);
298
- break;
299
- }
300
- case Opcodes.f64_ne: {
301
- if (stack.length < 2) { empty(); break; };
302
- const [ b, a ] = pop2();
303
- const v = bool(a !== b);
304
-
305
- replaceVal(v, Valtype.i32);
306
- push(v);
307
- break;
308
- }
309
- case Opcodes.f64_lt: {
310
- if (stack.length < 2) { empty(); break; };
311
- const [ b, a ] = pop2();
312
- const v = bool(a < b);
313
-
314
- replaceVal(v, Valtype.i32);
315
- push(v);
316
- break;
317
- }
318
- case Opcodes.f64_le: {
319
- if (stack.length < 2) { empty(); break; };
320
- const [ b, a ] = pop2();
321
- const v = bool(a <= b);
322
-
323
- replaceVal(v, Valtype.i32);
324
- push(v);
325
- break;
326
- }
327
- case Opcodes.f64_gt: {
328
- if (stack.length < 2) { empty(); break; };
329
- const [ b, a ] = pop2();
330
- const v = bool(a > b);
331
-
332
- replaceVal(v, Valtype.i32);
333
- push(v);
334
- break;
335
- }
336
- case Opcodes.f64_ge: {
337
- if (stack.length < 2) { empty(); break; };
338
- const [ b, a ] = pop2();
339
- const v = bool(a >= b);
340
-
341
- replaceVal(v, Valtype.i32);
342
- push(v);
343
- break;
344
- }
268
+ replaceVal(v, Valtype.i32);
269
+ push(v);
270
+ break;
271
+ }
272
+ case Opcodes.i32_shl: {
273
+ if (stack.length < 2) { empty(); break; };
274
+ const [ b, a ] = pop2();
275
+ const v = a << b;
345
276
 
346
- case Opcodes.f64_abs: {
347
- if (stack.length < 1) { empty(); break; };
348
- const v = Math.abs(pop());
277
+ replaceVal(v, Valtype.i32);
278
+ push(v);
279
+ break;
280
+ }
281
+ case Opcodes.i32_shr_s: {
282
+ if (stack.length < 2) { empty(); break; };
283
+ const [ b, a ] = pop2();
284
+ const v = a >> b;
349
285
 
350
- replaceVal(v, Valtype.f64);
351
- push(v);
352
- break;
353
- }
354
- case Opcodes.f64_neg: {
355
- if (stack.length < 1) { empty(); break; };
356
- const v = -pop();
286
+ replaceVal(v, Valtype.i32);
287
+ push(v);
288
+ break;
289
+ }
290
+ case Opcodes.i32_shr_u: {
291
+ if (stack.length < 2) { empty(); break; };
292
+ const [ b, a ] = pop2();
293
+ const v = a >>> b;
357
294
 
358
- replaceVal(v, Valtype.f64);
359
- push(v);
360
- break;
361
- }
295
+ replaceVal(v, Valtype.i32);
296
+ push(v);
297
+ break;
298
+ }
362
299
 
363
- case Opcodes.f64_ceil: {
364
- if (stack.length < 1) { empty(); break; };
365
- const v = Math.ceil(pop());
300
+ case Opcodes.f64_eq: {
301
+ if (stack.length < 2) { empty(); break; };
302
+ const [ b, a ] = pop2();
303
+ const v = bool(a === b);
366
304
 
367
- replaceVal(v, Valtype.f64);
368
- push(v);
369
- break;
370
- }
371
- case Opcodes.f64_floor: {
372
- if (stack.length < 1) { empty(); break; };
373
- const v = Math.floor(pop());
305
+ replaceVal(v, Valtype.i32);
306
+ push(v);
307
+ break;
308
+ }
309
+ case Opcodes.f64_ne: {
310
+ if (stack.length < 2) { empty(); break; };
311
+ const [ b, a ] = pop2();
312
+ const v = bool(a !== b);
374
313
 
375
- replaceVal(v, Valtype.f64);
376
- push(v);
377
- break;
378
- }
379
- case Opcodes.f64_trunc: {
380
- if (stack.length < 1) { empty(); break; };
381
- const v = Math.trunc(pop());
314
+ replaceVal(v, Valtype.i32);
315
+ push(v);
316
+ break;
317
+ }
318
+ case Opcodes.f64_lt: {
319
+ if (stack.length < 2) { empty(); break; };
320
+ const [ b, a ] = pop2();
321
+ const v = bool(a < b);
382
322
 
383
- replaceVal(v, Valtype.f64);
384
- push(v);
385
- break;
386
- }
387
- case Opcodes.f64_nearest: {
388
- if (stack.length < 1) { empty(); break; };
389
- const v = Math.round(pop());
323
+ replaceVal(v, Valtype.i32);
324
+ push(v);
325
+ break;
326
+ }
327
+ case Opcodes.f64_le: {
328
+ if (stack.length < 2) { empty(); break; };
329
+ const [ b, a ] = pop2();
330
+ const v = bool(a <= b);
390
331
 
391
- replaceVal(v, Valtype.f64);
392
- push(v);
393
- break;
394
- }
332
+ replaceVal(v, Valtype.i32);
333
+ push(v);
334
+ break;
335
+ }
336
+ case Opcodes.f64_gt: {
337
+ if (stack.length < 2) { empty(); break; };
338
+ const [ b, a ] = pop2();
339
+ const v = bool(a > b);
395
340
 
396
- case Opcodes.f64_sqrt: {
397
- if (stack.length < 1) { empty(); break; };
398
- const v = Math.sqrt(pop());
341
+ replaceVal(v, Valtype.i32);
342
+ push(v);
343
+ break;
344
+ }
345
+ case Opcodes.f64_ge: {
346
+ if (stack.length < 2) { empty(); break; };
347
+ const [ b, a ] = pop2();
348
+ const v = bool(a >= b);
399
349
 
400
- replaceVal(v, Valtype.f64);
401
- push(v);
402
- break;
403
- }
350
+ replaceVal(v, Valtype.i32);
351
+ push(v);
352
+ break;
353
+ }
404
354
 
405
- case Opcodes.f64_add: {
406
- if (stack.length < 2) { empty(); break; };
407
- const [ b, a ] = pop2();
408
- const v = a + b;
355
+ case Opcodes.f64_abs: {
356
+ if (stack.length < 1) { empty(); break; };
357
+ const v = Math.abs(pop());
409
358
 
410
- replaceVal(v, Valtype.f64);
411
- push(v);
412
- break;
413
- }
414
- case Opcodes.f64_sub: {
415
- if (stack.length < 2) { empty(); break; };
416
- const [ b, a ] = pop2();
417
- const v = a - b;
418
-
419
- replaceVal(v, Valtype.f64);
420
- push(v);
421
- break;
422
- }
423
- case Opcodes.f64_mul: {
424
- if (stack.length < 2) { empty(); break; };
425
- const [ b, a ] = pop2();
426
- const v = a * b;
427
-
428
- replaceVal(v, Valtype.f64);
429
- push(v);
430
- break;
431
- }
432
- case Opcodes.f64_div: {
433
- if (stack.length < 2) { empty(); break; };
434
- const [ b, a ] = pop2();
435
- const v = a / b;
436
-
437
- replaceVal(v, Valtype.f64);
438
- push(v);
439
- break;
440
- }
359
+ replaceVal(v, Valtype.f64);
360
+ push(v);
361
+ break;
362
+ }
363
+ case Opcodes.f64_neg: {
364
+ if (stack.length < 1) { empty(); break; };
365
+ const v = -pop();
441
366
 
442
- case Opcodes.f64_min: {
443
- if (stack.length < 2) { empty(); break; };
444
- const [ b, a ] = pop2();
445
- const v = Math.min(a, b);
367
+ replaceVal(v, Valtype.f64);
368
+ push(v);
369
+ break;
370
+ }
446
371
 
447
- replaceVal(v, Valtype.f64);
448
- push(v);
449
- break;
450
- }
451
- case Opcodes.f64_max: {
452
- if (stack.length < 2) { empty(); break; };
453
- const [ b, a ] = pop2();
454
- const v = Math.max(a, b);
455
-
456
- replaceVal(v, Valtype.f64);
457
- push(v);
458
- break;
459
- }
372
+ case Opcodes.f64_ceil: {
373
+ if (stack.length < 1) { empty(); break; };
374
+ const v = Math.ceil(pop());
375
+
376
+ replaceVal(v, Valtype.f64);
377
+ push(v);
378
+ break;
379
+ }
380
+ case Opcodes.f64_floor: {
381
+ if (stack.length < 1) { empty(); break; };
382
+ const v = Math.floor(pop());
460
383
 
461
- case Opcodes.f64_copysign: { // ?
462
- if (stack.length < 2) { empty(); break; };
463
- const [ b, a ] = pop2();
464
- const v = Math.abs(a) * (b > 0 ? 1 : -1);
384
+ replaceVal(v, Valtype.f64);
385
+ push(v);
386
+ break;
387
+ }
388
+ case Opcodes.f64_trunc: {
389
+ if (stack.length < 1) { empty(); break; };
390
+ const v = Math.trunc(pop());
465
391
 
466
- replaceVal(v, Valtype.f64);
467
- push(v);
468
- break;
469
- }
392
+ replaceVal(v, Valtype.f64);
393
+ push(v);
394
+ break;
395
+ }
396
+ case Opcodes.f64_nearest: {
397
+ if (stack.length < 1) { empty(); break; };
398
+ const v = Math.round(pop());
470
399
 
471
- case Opcodes.f64_convert_i32_s:
472
- case Opcodes.f64_convert_i32_u: {
473
- if (stack.length < 1) { empty(); break; };
474
- const v = pop();
400
+ replaceVal(v, Valtype.f64);
401
+ push(v);
402
+ break;
403
+ }
475
404
 
476
- replaceVal(v, Valtype.f64);
477
- push(v);
478
- break;
479
- }
405
+ case Opcodes.f64_sqrt: {
406
+ if (stack.length < 1) { empty(); break; };
407
+ const v = Math.sqrt(pop());
480
408
 
481
- case 0xfc02: // i32.trunc_sat_f64_s
482
- case 0xfc03: { // i32.trunc_sat_f64_u
483
- if (stack.length < 1) { empty(); break; }
484
- const v = pop();
409
+ replaceVal(v, Valtype.f64);
410
+ push(v);
411
+ break;
412
+ }
485
413
 
486
- replaceVal(v, Valtype.i32);
487
- push(v);
488
- break;
489
- }
414
+ case Opcodes.f64_add: {
415
+ if (stack.length < 2) { empty(); break; };
416
+ const [ b, a ] = pop2();
417
+ const v = a + b;
490
418
 
491
- case Opcodes.drop: {
492
- if (stack.length < 1) { empty(); break; }
493
- pop();
494
- break;
495
- }
419
+ replaceVal(v, Valtype.f64);
420
+ push(v);
421
+ break;
422
+ }
423
+ case Opcodes.f64_sub: {
424
+ if (stack.length < 2) { empty(); break; };
425
+ const [ b, a ] = pop2();
426
+ const v = a - b;
496
427
 
497
- case Opcodes.local_get: {
498
- const x = locals[op[1]];
499
- if (x === false) {
500
- empty();
501
- } else {
428
+ replaceVal(v, Valtype.f64);
429
+ push(v);
430
+ break;
431
+ }
432
+ case Opcodes.f64_mul: {
433
+ if (stack.length < 2) { empty(); break; };
434
+ const [ b, a ] = pop2();
435
+ const v = a * b;
436
+
437
+ replaceVal(v, Valtype.f64);
438
+ push(v);
439
+ break;
440
+ }
441
+ case Opcodes.f64_div: {
442
+ if (stack.length < 2) { empty(); break; };
443
+ const [ b, a ] = pop2();
444
+ const v = a / b;
445
+
446
+ replaceVal(v, Valtype.f64);
447
+ push(v);
448
+ break;
449
+ }
450
+
451
+ case Opcodes.f64_min: {
452
+ if (stack.length < 2) { empty(); break; };
453
+ const [ b, a ] = pop2();
454
+ const v = Math.min(a, b);
455
+
456
+ replaceVal(v, Valtype.f64);
457
+ push(v);
458
+ break;
459
+ }
460
+ case Opcodes.f64_max: {
461
+ if (stack.length < 2) { empty(); break; };
462
+ const [ b, a ] = pop2();
463
+ const v = Math.max(a, b);
464
+
465
+ replaceVal(v, Valtype.f64);
466
+ push(v);
467
+ break;
468
+ }
469
+
470
+ case Opcodes.f64_copysign: { // ?
471
+ if (stack.length < 2) { empty(); break; };
472
+ const [ b, a ] = pop2();
473
+ const v = Math.abs(a) * (b > 0 ? 1 : -1);
474
+
475
+ replaceVal(v, Valtype.f64);
476
+ push(v);
477
+ break;
478
+ }
479
+
480
+ case Opcodes.f64_convert_i32_s:
481
+ case Opcodes.f64_convert_i32_u: {
482
+ if (stack.length < 1) { empty(); break; };
483
+ const v = pop();
484
+
485
+ replaceVal(v, Valtype.f64);
486
+ push(v);
487
+ break;
488
+ }
489
+
490
+ case 0xfc02: // i32.trunc_sat_f64_s
491
+ case 0xfc03: { // i32.trunc_sat_f64_u
492
+ if (stack.length < 1) { empty(); break; }
493
+ const v = pop();
494
+
495
+ replaceVal(v, Valtype.i32);
496
+ push(v);
497
+ break;
498
+ }
499
+
500
+ case Opcodes.drop: {
501
+ if (stack.length < 1) { empty(); break; }
502
+ pop();
503
+ break;
504
+ }
505
+
506
+ case Opcodes.local_get: {
507
+ const x = locals[op[1]];
508
+ if (x === false) {
509
+ localNeeded[op[1]] |= 0b01;
510
+ empty();
511
+ } else {
512
+ replaceVal(x, localValtypes[op[1]]);
513
+ push(x);
514
+ }
515
+ break;
516
+ }
517
+
518
+ case Opcodes.local_set: {
519
+ if (pass === 1) {
520
+ if (localNeeded[op[1]] === 0) {
521
+ // todo: breaks some bad assembler local code
522
+ // delete _locals[localNames[op[1]]];
523
+
524
+ pop();
525
+ wasm.splice(i, 1);
526
+ i--;
527
+ break;
528
+ }
529
+ }
530
+
531
+ if (stack.length < 1) {
532
+ localNeeded[op[1]] |= 0b10;
533
+ locals[op[1]] = false;
534
+ empty();
535
+ break;
536
+ }
537
+
538
+ const x = popWithoutRemove();
539
+ locals[op[1]] = x;
540
+ break;
541
+ }
542
+
543
+ case Opcodes.local_tee: {
544
+ if (pass === 1) {
545
+ if (localNeeded[op[1]] === 0) {
546
+ // todo: breaks some bad assembler local code
547
+ // delete _locals[localNames[op[1]]];
548
+
549
+ pop();
550
+ wasm.splice(i, 1);
551
+ i--;
552
+ break;
553
+ }
554
+ }
555
+
556
+ if (stack.length < 1) {
557
+ localNeeded[op[1]] |= 0b10;
558
+ locals[op[1]] = false;
559
+ empty();
560
+ break;
561
+ }
562
+
563
+ const x = pop();
564
+ locals[op[1]] = x;
502
565
  replaceVal(x, localValtypes[op[1]]);
503
566
  push(x);
567
+ break;
504
568
  }
505
- break;
506
- }
507
569
 
508
- case Opcodes.local_set: {
509
- if (stack.length < 1) {
510
- locals[op[1]] = false;
511
- empty();
570
+ case Opcodes.block:
571
+ case Opcodes.loop:
572
+ case Opcodes.try:
573
+ case Opcodes.if:
574
+ case Opcodes.else:
575
+ case Opcodes.catch:
576
+ case Opcodes.end: {
577
+ reset();
512
578
  break;
513
579
  }
514
580
 
515
- const x = popWithoutRemove();
516
- locals[op[1]] = x;
517
- break;
518
- }
519
-
520
- case Opcodes.local_tee: {
521
- if (stack.length < 1) {
522
- locals[op[1]] = false;
581
+ default: {
523
582
  empty();
524
583
  break;
525
584
  }
526
-
527
- const x = pop();
528
- locals[op[1]] = x;
529
- replaceVal(x, localValtypes[op[1]]);
530
- push(x);
531
- break;
532
585
  }
533
586
 
534
- case Opcodes.block:
535
- case Opcodes.loop:
536
- case Opcodes.try:
537
- case Opcodes.if:
538
- case Opcodes.else:
539
- case Opcodes.catch:
540
- case Opcodes.end: {
541
- resetLocals();
542
- empty();
543
- break;
544
- }
587
+ // this does, eg:
588
+ // local.get 7 ;; $i (i32)
589
+ // f64.convert_i32_s
590
+ // f64.const 1
591
+ // f64.add
592
+ // i32.trunc_sat_f64_s <--
593
+ // local.set 7 ;; $i (i32)
594
+ // ->
595
+ // local.get 7 ;; $i (i32)
596
+ // i32.const 1
597
+ // i32.add
598
+ // local.set 7 ;; $i (i32)
599
+ // if (i >= 2 &&
600
+ // ((opcode >= 0xa0 && opcode <= 0xa3) || // main f64 math op
601
+ // (opcode >= 0x61 && opcode <= 0x66)) // main f64 eq op
602
+ // ) {
603
+ // const o2 = wasm[i - 1][0];
604
+ // if (o2 === Opcodes.f64_const) { // f64.const
605
+ // const o3 = wasm[i - 2][0];
606
+ // if (o3 === Opcodes.f64_convert_i32_s || o3 === Opcodes.f64_convert_i32_u) {
607
+ // // remove now unneeded i32 -> f64 convert
608
+ // wasm.splice(i - 2, 1);
609
+ // i--;
610
+
611
+ // // convert f64.const -> i32.const
612
+ // const n = wasm[i - 1][1];
613
+ // wasm.splice(i - 1, 1, number(n, Valtype.i32));
614
+
615
+ // // convert math op from f64 to i32
616
+ // wasm[i][0] = f64ToI32Op[wasm[i][0]];
617
+
618
+ // const nextOp = wasm[i + 1];
619
+ // if (nextOp && opcode >= 0xa0 && opcode <= 0xa3) {
620
+ // if (nextOp[0] === 0xfc && (nextOp[1] === 0x02 || nextOp[1] === 0x03)) {
621
+ // // remove optional unneeded f64 -> i32 convert after
622
+ // wasm.splice(i + 1, 1);
623
+ // } else {
624
+ // // add now needed i32 -> f64 convert after
625
+ // wasm.splice(i + 1, Opcodes.i32_trunc_sat_f64_s);
626
+ // }
627
+ // }
628
+ // }
629
+ // }
630
+ // }
545
631
 
546
- default: {
547
- empty();
548
- break;
549
- }
632
+ // if ((opcode === 0xfc02 || opcode === 0xfc03) && i >= 3) { // i32.trunc_sat_f64_s/u
633
+ // const o2 = wasm[i - 1][0];
634
+ // if (
635
+ // (o2 >= 0xa0 && o2 <= 0xa3) || // main f64 math op
636
+ // (o2 >= 0x61 && o2 <= 0x66) // main f64 eq op
637
+ // ) {
638
+ // const o3 = wasm[i - 2][0];
639
+ // if (o3 === Opcodes.f64_const) { // f64.const
640
+ // const o4 = wasm[i - 3][0];
641
+ // if (o4 === Opcodes.f64_convert_i32_s || o4 === Opcodes.f64_convert_i32_u) {
642
+ // // remove now unneeded i32 -> f64 convert
643
+ // wasm.splice(i - 3, 1);
644
+ // i--;
645
+ // } else {
646
+ // // add now needed f64 -> i32 convert prior
647
+ // wasm.splice(i - 2, 0, Opcodes.i32_trunc_sat_f64_s);
648
+ // i++;
649
+ // }
650
+
651
+ // // convert f64.const -> i32.const
652
+ // const n = wasm[i - 2][1];
653
+ // wasm.splice(i - 2, 1, number(n, Valtype.i32));
654
+
655
+ // // convert math op from f64 to i32
656
+ // wasm[i - 1][0] = f64ToI32Op[wasm[i - 1][0]];
657
+
658
+ // // remove this now unneeded f64 -> i32 convert
659
+ // wasm.splice(i, 1);
660
+ // }
661
+ // }
662
+ // }
550
663
  }
551
-
552
- // this does, eg:
553
- // local.get 7 ;; $i (i32)
554
- // f64.convert_i32_s
555
- // f64.const 1
556
- // f64.add
557
- // i32.trunc_sat_f64_s <--
558
- // local.set 7 ;; $i (i32)
559
- // ->
560
- // local.get 7 ;; $i (i32)
561
- // i32.const 1
562
- // i32.add
563
- // local.set 7 ;; $i (i32)
564
- // if (i >= 2 &&
565
- // ((opcode >= 0xa0 && opcode <= 0xa3) || // main f64 math op
566
- // (opcode >= 0x61 && opcode <= 0x66)) // main f64 eq op
567
- // ) {
568
- // const o2 = wasm[i - 1][0];
569
- // if (o2 === Opcodes.f64_const) { // f64.const
570
- // const o3 = wasm[i - 2][0];
571
- // if (o3 === Opcodes.f64_convert_i32_s || o3 === Opcodes.f64_convert_i32_u) {
572
- // // remove now unneeded i32 -> f64 convert
573
- // wasm.splice(i - 2, 1);
574
- // i--;
575
-
576
- // // convert f64.const -> i32.const
577
- // const n = wasm[i - 1][1];
578
- // wasm.splice(i - 1, 1, number(n, Valtype.i32));
579
-
580
- // // convert math op from f64 to i32
581
- // wasm[i][0] = f64ToI32Op[wasm[i][0]];
582
-
583
- // const nextOp = wasm[i + 1];
584
- // if (nextOp && opcode >= 0xa0 && opcode <= 0xa3) {
585
- // if (nextOp[0] === 0xfc && (nextOp[1] === 0x02 || nextOp[1] === 0x03)) {
586
- // // remove optional unneeded f64 -> i32 convert after
587
- // wasm.splice(i + 1, 1);
588
- // } else {
589
- // // add now needed i32 -> f64 convert after
590
- // wasm.splice(i + 1, Opcodes.i32_trunc_sat_f64_s);
591
- // }
592
- // }
593
- // }
594
- // }
595
- // }
596
-
597
- // if ((opcode === 0xfc02 || opcode === 0xfc03) && i >= 3) { // i32.trunc_sat_f64_s/u
598
- // const o2 = wasm[i - 1][0];
599
- // if (
600
- // (o2 >= 0xa0 && o2 <= 0xa3) || // main f64 math op
601
- // (o2 >= 0x61 && o2 <= 0x66) // main f64 eq op
602
- // ) {
603
- // const o3 = wasm[i - 2][0];
604
- // if (o3 === Opcodes.f64_const) { // f64.const
605
- // const o4 = wasm[i - 3][0];
606
- // if (o4 === Opcodes.f64_convert_i32_s || o4 === Opcodes.f64_convert_i32_u) {
607
- // // remove now unneeded i32 -> f64 convert
608
- // wasm.splice(i - 3, 1);
609
- // i--;
610
- // } else {
611
- // // add now needed f64 -> i32 convert prior
612
- // wasm.splice(i - 2, 0, Opcodes.i32_trunc_sat_f64_s);
613
- // i++;
614
- // }
615
-
616
- // // convert f64.const -> i32.const
617
- // const n = wasm[i - 2][1];
618
- // wasm.splice(i - 2, 1, number(n, Valtype.i32));
619
-
620
- // // convert math op from f64 to i32
621
- // wasm[i - 1][0] = f64ToI32Op[wasm[i - 1][0]];
622
-
623
- // // remove this now unneeded f64 -> i32 convert
624
- // wasm.splice(i, 1);
625
- // }
626
- // }
627
- // }
628
664
  }
629
665
  };