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.
- package/compiler/builtins/array.ts +23 -0
- package/compiler/builtins/regexp.ts +62 -0
- package/compiler/builtins_precompiled.js +1388 -1383
- package/compiler/codegen.js +82 -72
- package/compiler/cyclone.js +580 -544
- package/compiler/opt.js +8 -14
- package/compiler/parse.js +3 -1
- package/compiler/precompile.js +2 -2
- package/compiler/prototype.js +0 -49
- package/compiler/wrap.js +1 -3
- package/fuzz/generator.js +201 -0
- package/fuzz/index.js +270 -0
- package/package.json +1 -1
- package/runtime/index.js +1 -1
- package/foo.js +0 -4
package/compiler/cyclone.js
CHANGED
@@ -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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
34
|
-
|
35
|
+
while (passes.length > 0) {
|
36
|
+
const pass = passes.shift();
|
35
37
|
|
36
|
-
let
|
37
|
-
|
38
|
-
|
39
|
-
}
|
38
|
+
let stack = []; // "stack"
|
39
|
+
const empty = () => {
|
40
|
+
stack = [];
|
41
|
+
};
|
40
42
|
|
41
|
-
const
|
42
|
-
|
43
|
+
const reset = () => {
|
44
|
+
locals = new Array(locals.length).fill(false);
|
45
|
+
empty();
|
43
46
|
};
|
44
47
|
|
45
|
-
|
46
|
-
|
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
|
-
|
49
|
-
|
50
|
-
const popped = stack.pop();
|
51
|
-
// debugPops.unshift({ ...popped, index: wasm.indexOf(popped.op) });
|
122
|
+
break;
|
123
|
+
}
|
52
124
|
|
53
|
-
|
54
|
-
|
55
|
-
|
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
|
-
|
58
|
-
|
59
|
-
|
136
|
+
case Opcodes.i32_eqz: {
|
137
|
+
if (stack.length < 1) { empty(); break; };
|
138
|
+
const v = bool(pop() === 0);
|
60
139
|
|
61
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
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
|
-
|
76
|
-
|
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
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
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
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
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
|
-
|
111
|
-
|
194
|
+
replaceVal(v, Valtype.i32);
|
195
|
+
push(v);
|
196
|
+
break;
|
197
|
+
}
|
112
198
|
|
113
|
-
|
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
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
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
|
-
|
128
|
-
|
129
|
-
|
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
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
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
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
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
|
-
|
196
|
-
|
197
|
-
|
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
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
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
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
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
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
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
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
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
|
-
|
347
|
-
|
348
|
-
|
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
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
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
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
295
|
+
replaceVal(v, Valtype.i32);
|
296
|
+
push(v);
|
297
|
+
break;
|
298
|
+
}
|
362
299
|
|
363
|
-
|
364
|
-
|
365
|
-
|
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
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
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
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
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
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
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
|
-
|
392
|
-
|
393
|
-
|
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
|
-
|
397
|
-
|
398
|
-
|
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
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
350
|
+
replaceVal(v, Valtype.i32);
|
351
|
+
push(v);
|
352
|
+
break;
|
353
|
+
}
|
404
354
|
|
405
|
-
|
406
|
-
|
407
|
-
|
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
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
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
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
367
|
+
replaceVal(v, Valtype.f64);
|
368
|
+
push(v);
|
369
|
+
break;
|
370
|
+
}
|
446
371
|
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
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
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
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
|
-
|
467
|
-
|
468
|
-
|
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
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
400
|
+
replaceVal(v, Valtype.f64);
|
401
|
+
push(v);
|
402
|
+
break;
|
403
|
+
}
|
475
404
|
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
}
|
405
|
+
case Opcodes.f64_sqrt: {
|
406
|
+
if (stack.length < 1) { empty(); break; };
|
407
|
+
const v = Math.sqrt(pop());
|
480
408
|
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
409
|
+
replaceVal(v, Valtype.f64);
|
410
|
+
push(v);
|
411
|
+
break;
|
412
|
+
}
|
485
413
|
|
486
|
-
|
487
|
-
|
488
|
-
|
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
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
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
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
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
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
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
|
-
|
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
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
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
|
-
|
547
|
-
|
548
|
-
|
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
|
};
|