porffor 0.16.0-594397507 → 0.16.0-6572d1c74

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.
@@ -1078,7 +1078,7 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
1078
1078
  locals,
1079
1079
  localInd: allLocals.length,
1080
1080
  returns,
1081
- returnType: returnType ?? TYPES.number,
1081
+ returnType,
1082
1082
  internal: true,
1083
1083
  index: currentFuncIndex++,
1084
1084
  table
@@ -1254,7 +1254,7 @@ const getNodeType = (scope, node) => {
1254
1254
  const func = funcs.find(x => x.name === name);
1255
1255
 
1256
1256
  if (func) {
1257
- if (func.returnType) return func.returnType;
1257
+ if (func.returnType != null) return func.returnType;
1258
1258
  }
1259
1259
 
1260
1260
  if (builtinFuncs[name] && !builtinFuncs[name].typedReturns) return builtinFuncs[name].returnType ?? TYPES.number;
@@ -1270,15 +1270,7 @@ const getNodeType = (scope, node) => {
1270
1270
  const func = spl[spl.length - 1];
1271
1271
  const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES.bytestring && prototypeFuncs[x][func] != null);
1272
1272
  if (protoFuncs.length === 1) {
1273
- if (protoFuncs[0].returnType) return protoFuncs[0].returnType;
1274
- }
1275
-
1276
- if (protoFuncs.length > 0) {
1277
- if (scope.locals['#last_type']) return getLastType(scope);
1278
-
1279
- // presume
1280
- // todo: warn here?
1281
- return TYPES.number;
1273
+ if (protoFuncs[0].returnType != null) return protoFuncs[0].returnType;
1282
1274
  }
1283
1275
  }
1284
1276
 
@@ -1815,7 +1807,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1815
1807
  f64_store: { imms: 2, args: [ true, false ], returns: 0 },
1816
1808
 
1817
1809
  // value
1818
- i32_const: { imms: 1, args: [], returns: 1 },
1810
+ i32_const: { imms: 1, args: [], returns: 0 },
1819
1811
  };
1820
1812
 
1821
1813
  const opName = name.slice('__Porffor_wasm_'.length);
@@ -1978,7 +1970,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1978
1970
  const func = funcs[idx - importedFuncs.length]; // idx === scope.index ? scope : funcs.find(x => x.index === idx);
1979
1971
  const userFunc = func && !func.internal;
1980
1972
  const typedParams = userFunc || builtinFuncs[name]?.typedParams;
1981
- const typedReturns = (func && func.returnType == null) || builtinFuncs[name]?.typedReturns;
1973
+ const typedReturns = (userFunc && func.returnType == null) || builtinFuncs[name]?.typedReturns;
1982
1974
  const paramCount = func && (typedParams ? func.params.length / 2 : func.params.length);
1983
1975
 
1984
1976
  let args = decl.arguments;
@@ -2007,8 +1999,8 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2007
1999
  }
2008
2000
 
2009
2001
  if (valtypeBinary !== Valtype.i32 && (
2010
- (builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32) ||
2011
- (importedFuncs[name] && name.startsWith('profile'))
2002
+ (builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32)
2003
+ // (importedFuncs[name] && name.startsWith('profile'))
2012
2004
  )) {
2013
2005
  out.push(Opcodes.i32_to);
2014
2006
  }
@@ -2189,7 +2181,7 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
2189
2181
  if (Prefs.typeswitchUseBrtable)
2190
2182
  return brTable(type, bc, returns);
2191
2183
 
2192
- const tmp = localTmp(scope, '#typeswitch_tmp', Valtype.i32);
2184
+ const tmp = localTmp(scope, '#typeswitch_tmp' + (Prefs.typeswitchUniqueTmp ? randId() : ''), Valtype.i32);
2193
2185
  const out = [
2194
2186
  ...type,
2195
2187
  [ Opcodes.local_set, tmp ],
@@ -2571,7 +2563,7 @@ const generateUnary = (scope, decl) => {
2571
2563
  // * -1
2572
2564
 
2573
2565
  if (decl.prefix && decl.argument.type === 'Literal' && typeof decl.argument.value === 'number') {
2574
- // if -<N>, just return that
2566
+ // if -n, just return that as a const
2575
2567
  return number(-1 * decl.argument.value);
2576
2568
  }
2577
2569
 
@@ -2583,14 +2575,14 @@ const generateUnary = (scope, decl) => {
2583
2575
  case '!':
2584
2576
  const arg = decl.argument;
2585
2577
  if (arg.type === 'UnaryExpression' && arg.operator === '!') {
2586
- // !!x -> is x truthy
2578
+ // opt: !!x -> is x truthy
2587
2579
  return truthy(scope, generate(scope, arg.argument), getNodeType(scope, arg.argument), false, false);
2588
2580
  }
2581
+
2589
2582
  // !=
2590
- return falsy(scope, generate(scope, decl.argument), getNodeType(scope, decl.argument), false, false);
2583
+ return falsy(scope, generate(scope, arg), getNodeType(scope, arg), false, false);
2591
2584
 
2592
2585
  case '~':
2593
- // todo: does not handle Infinity properly (should convert to 0) (but opt const converting saves us sometimes)
2594
2586
  return [
2595
2587
  ...generate(scope, decl.argument),
2596
2588
  Opcodes.i32_to,
@@ -3510,7 +3502,7 @@ const generateMember = (scope, decl, _global, _name) => {
3510
3502
  }
3511
3503
 
3512
3504
  if (builtinFuncs[name]) return withType(scope, number(builtinFuncs[name].typedParams ? (builtinFuncs[name].params.length / 2) : builtinFuncs[name].params.length), TYPES.number);
3513
- if (importedFuncs[name]) return withType(scope, number(importedFuncs[name].params), TYPES.number);
3505
+ if (importedFuncs[name]) return withType(scope, number(importedFuncs[name].params.length ?? importedFuncs[name].params), TYPES.number);
3514
3506
  if (internalConstrs[name]) return withType(scope, number(internalConstrs[name].length ?? 0), TYPES.number);
3515
3507
 
3516
3508
  if (Prefs.fastLength) {
@@ -3979,19 +3971,8 @@ export default program => {
3979
3971
  data = [];
3980
3972
  currentFuncIndex = importedFuncs.length;
3981
3973
 
3982
- globalThis.valtype = 'f64';
3983
-
3984
- const valtypeOpt = process.argv.find(x => x.startsWith('--valtype='));
3985
- if (valtypeOpt) valtype = valtypeOpt.split('=')[1];
3986
-
3987
- globalThis.valtypeBinary = Valtype[valtype];
3988
-
3989
3974
  const valtypeInd = ['i32', 'i64', 'f64'].indexOf(valtype);
3990
3975
 
3991
- globalThis.pageSize = PageSize;
3992
- const pageSizeOpt = process.argv.find(x => x.startsWith('--page-size='));
3993
- if (pageSizeOpt) pageSize = parseInt(pageSizeOpt.split('=')[1]) * 1024;
3994
-
3995
3976
  // set generic opcodes for current valtype
3996
3977
  Opcodes.const = [ Opcodes.i32_const, Opcodes.i64_const, Opcodes.f64_const ][valtypeInd];
3997
3978
  Opcodes.eq = [ Opcodes.i32_eq, Opcodes.i64_eq, Opcodes.f64_eq ][valtypeInd];
@@ -0,0 +1,535 @@
1
+ // cyclone: wasm partial constant evaluator (it is fast and dangerous hence "cyclone")
2
+ import { signedLEB128, ieee754_binary64, read_ieee754_binary64, read_signedLEB128 } from './encoding.js';
3
+ import { Opcodes, Valtype } from './wasmSpec.js';
4
+
5
+ const number = (n, valtype = valtypeBinary) => {
6
+ switch (valtype) {
7
+ case Valtype.i32: return [ Opcodes.i32_const, ...signedLEB128(n) ];
8
+ case Valtype.i64: return [ Opcodes.i64_const, ...signedLEB128(n) ];
9
+ case Valtype.f64: return [ Opcodes.f64_const, ...ieee754_binary64(n) ];
10
+ }
11
+ };
12
+
13
+ const f64ToI32Op = {
14
+ [Opcodes.f64_eq]: Opcodes.i32_eq,
15
+ [Opcodes.f64_ne]: Opcodes.i32_ne,
16
+ [Opcodes.f64_lt]: Opcodes.i32_lt_s,
17
+ [Opcodes.f64_le]: Opcodes.i32_le_s,
18
+ [Opcodes.f64_gt]: Opcodes.i32_gt_s,
19
+ [Opcodes.f64_ge]: Opcodes.i32_ge_s,
20
+ [Opcodes.f64_add]: Opcodes.i32_add,
21
+ [Opcodes.f64_sub]: Opcodes.i32_sub,
22
+ [Opcodes.f64_mul]: Opcodes.i32_mul,
23
+ [Opcodes.f64_div]: Opcodes.i32_div_s,
24
+ };
25
+
26
+ export default wasm => {
27
+ let stack = []; // """""stack"""""
28
+ for (let i = 0; i < wasm.length; i++) {
29
+ let op = wasm[i];
30
+ if (!op) continue;
31
+
32
+ // op = [ ...op.filter(x => x != null && x <= 0xff) ];
33
+ op = [ ...op ];
34
+ wasm[i] = op;
35
+
36
+ let opcode = op[0];
37
+ if (opcode === 0xfc) { // multibyte op
38
+ opcode = (opcode << 8) + op[1];
39
+ }
40
+
41
+ const push = val => {
42
+ stack.push({ val, op });
43
+ };
44
+
45
+ const pop = () => {
46
+ const popped = stack.pop();
47
+
48
+ // remove the op
49
+ wasm.splice(wasm.indexOf(popped.op), 1);
50
+ i--;
51
+
52
+ return popped.val;
53
+ };
54
+
55
+ const pop2 = () => [ pop(), pop() ];
56
+
57
+ const bool = v => v ? 1 : 0;
58
+
59
+ const replaceOp = newOp => {
60
+ op.splice(0, op.length, ...newOp);
61
+ };
62
+ const replaceVal = (val, valtype) => replaceOp(number(val, valtype));
63
+
64
+ const empty = () => {
65
+ stack = [];
66
+ };
67
+
68
+ switch (opcode) {
69
+ case Opcodes.i32_const: {
70
+ const n = read_signedLEB128(op.slice(1));
71
+ push(n);
72
+ break;
73
+ }
74
+ case Opcodes.f64_const: {
75
+ const n = read_ieee754_binary64(op.slice(1));
76
+ push(n);
77
+ break;
78
+ }
79
+
80
+ case Opcodes.i32_eqz: {
81
+ if (stack.length < 1) { empty(); break; };
82
+ const v = bool(pop() === 0);
83
+
84
+ replaceVal(v, Valtype.i32);
85
+ push(v);
86
+ break;
87
+ }
88
+ case Opcodes.i32_eq: {
89
+ if (stack.length < 2) { empty(); break; };
90
+ const [ b, a ] = pop2();
91
+ const v = bool(a === b);
92
+
93
+ replaceVal(v, Valtype.i32);
94
+ push(v);
95
+ break;
96
+ }
97
+ case Opcodes.i32_ne: {
98
+ if (stack.length < 2) { empty(); break; };
99
+ const [ b, a ] = pop2();
100
+ const v = bool(a !== b);
101
+
102
+ replaceVal(v, Valtype.i32);
103
+ push(v);
104
+ break;
105
+ }
106
+ case Opcodes.i32_lt_s: {
107
+ if (stack.length < 2) { empty(); break; };
108
+ const [ b, a ] = pop2();
109
+ const v = bool(a < b);
110
+
111
+ replaceVal(v, Valtype.i32);
112
+ push(v);
113
+ break;
114
+ }
115
+ case Opcodes.i32_le_s: {
116
+ if (stack.length < 2) { empty(); break; };
117
+ const [ b, a ] = pop2();
118
+ const v = bool(a <= b);
119
+
120
+ replaceVal(v, Valtype.i32);
121
+ push(v);
122
+ break;
123
+ }
124
+ case Opcodes.i32_gt_s: {
125
+ if (stack.length < 2) { empty(); break; };
126
+ const [ b, a ] = pop2();
127
+ const v = bool(a > b);
128
+
129
+ replaceVal(v, Valtype.i32);
130
+ push(v);
131
+ break;
132
+ }
133
+ case Opcodes.i32_ge_s: {
134
+ if (stack.length < 2) { empty(); break; };
135
+ const [ b, a ] = pop2();
136
+ const v = bool(a >= b);
137
+
138
+ replaceVal(v, Valtype.i32);
139
+ push(v);
140
+ break;
141
+ }
142
+
143
+ case Opcodes.i32_add: {
144
+ if (stack.length < 2) { empty(); break; };
145
+ const [ b, a ] = pop2();
146
+ const v = a + b;
147
+
148
+ replaceVal(v, Valtype.i32);
149
+ push(v);
150
+ break;
151
+ }
152
+ case Opcodes.i32_sub: {
153
+ if (stack.length < 2) { empty(); break; };
154
+ const [ b, a ] = pop2();
155
+ const v = a - b;
156
+
157
+ replaceVal(v, Valtype.i32);
158
+ push(v);
159
+ break;
160
+ }
161
+ case Opcodes.i32_mul: {
162
+ if (stack.length < 2) { empty(); break; };
163
+ const [ b, a ] = pop2();
164
+ const v = a * b;
165
+
166
+ replaceVal(v, Valtype.i32);
167
+ push(v);
168
+ break;
169
+ }
170
+ case Opcodes.i32_div_s: {
171
+ if (stack.length < 2) { empty(); break; };
172
+ const [ b, a ] = pop2();
173
+ const v = a / b;
174
+
175
+ replaceVal(v, Valtype.i32);
176
+ push(v);
177
+ break;
178
+ }
179
+ case Opcodes.i32_rem_s: {
180
+ if (stack.length < 2) { empty(); break; };
181
+ const [ b, a ] = pop2();
182
+ const v = a % b; // not rem but good enough
183
+
184
+ replaceVal(v, Valtype.i32);
185
+ push(v);
186
+ break;
187
+ }
188
+
189
+ case Opcodes.i32_and: {
190
+ if (stack.length < 2) { empty(); break; };
191
+ const [ b, a ] = pop2();
192
+ const v = a & b;
193
+
194
+ replaceVal(v, Valtype.i32);
195
+ push(v);
196
+ break;
197
+ }
198
+ case Opcodes.i32_or: {
199
+ if (stack.length < 2) { empty(); break; };
200
+ const [ b, a ] = pop2();
201
+ const v = a | b;
202
+
203
+ replaceVal(v, Valtype.i32);
204
+ push(v);
205
+ break;
206
+ }
207
+ case Opcodes.i32_xor: {
208
+ if (stack.length < 2) { empty(); break; };
209
+ const [ b, a ] = pop2();
210
+ const v = a ^ b;
211
+
212
+ replaceVal(v, Valtype.i32);
213
+ push(v);
214
+ break;
215
+ }
216
+ case Opcodes.i32_shl: {
217
+ if (stack.length < 2) { empty(); break; };
218
+ const [ b, a ] = pop2();
219
+ const v = a << b;
220
+
221
+ replaceVal(v, Valtype.i32);
222
+ push(v);
223
+ break;
224
+ }
225
+ case Opcodes.i32_shr_s: {
226
+ if (stack.length < 2) { empty(); break; };
227
+ const [ b, a ] = pop2();
228
+ const v = a >> b;
229
+
230
+ replaceVal(v, Valtype.i32);
231
+ push(v);
232
+ break;
233
+ }
234
+ case Opcodes.i32_shr_u: {
235
+ if (stack.length < 2) { empty(); break; };
236
+ const [ b, a ] = pop2();
237
+ const v = a >>> b;
238
+
239
+ replaceVal(v, Valtype.i32);
240
+ push(v);
241
+ break;
242
+ }
243
+
244
+ case Opcodes.f64_eq: {
245
+ if (stack.length < 2) { empty(); break; };
246
+ const [ b, a ] = pop2();
247
+ const v = bool(a === b);
248
+
249
+ replaceVal(v, Valtype.f64);
250
+ push(v);
251
+ break;
252
+ }
253
+ case Opcodes.f64_ne: {
254
+ if (stack.length < 2) { empty(); break; };
255
+ const [ b, a ] = pop2();
256
+ const v = bool(a !== b);
257
+
258
+ replaceVal(v, Valtype.f64);
259
+ push(v);
260
+ break;
261
+ }
262
+ case Opcodes.f64_lt: {
263
+ if (stack.length < 2) { empty(); break; };
264
+ const [ b, a ] = pop2();
265
+ const v = bool(a < b);
266
+
267
+ replaceVal(v, Valtype.f64);
268
+ push(v);
269
+ break;
270
+ }
271
+ case Opcodes.f64_le: {
272
+ if (stack.length < 2) { empty(); break; };
273
+ const [ b, a ] = pop2();
274
+ const v = bool(a <= b);
275
+
276
+ replaceVal(v, Valtype.f64);
277
+ push(v);
278
+ break;
279
+ }
280
+ case Opcodes.f64_gt: {
281
+ if (stack.length < 2) { empty(); break; };
282
+ const [ b, a ] = pop2();
283
+ const v = bool(a > b);
284
+
285
+ replaceVal(v, Valtype.f64);
286
+ push(v);
287
+ break;
288
+ }
289
+ case Opcodes.f64_ge: {
290
+ if (stack.length < 2) { empty(); break; };
291
+ const [ b, a ] = pop2();
292
+ const v = bool(a >= b);
293
+
294
+ replaceVal(v, Valtype.f64);
295
+ push(v);
296
+ break;
297
+ }
298
+
299
+ case Opcodes.f64_abs: {
300
+ if (stack.length < 1) { empty(); break; };
301
+ const v = Math.abs(pop());
302
+
303
+ replaceVal(v, Valtype.f64);
304
+ push(v);
305
+ break;
306
+ }
307
+ case Opcodes.f64_neg: {
308
+ if (stack.length < 1) { empty(); break; };
309
+ const v = -pop();
310
+
311
+ replaceVal(v, Valtype.f64);
312
+ push(v);
313
+ break;
314
+ }
315
+
316
+ case Opcodes.f64_ceil: {
317
+ if (stack.length < 1) { empty(); break; };
318
+ const v = Math.ceil(pop());
319
+
320
+ replaceVal(v, Valtype.f64);
321
+ push(v);
322
+ break;
323
+ }
324
+ case Opcodes.f64_floor: {
325
+ if (stack.length < 1) { empty(); break; };
326
+ const v = Math.floor(pop());
327
+
328
+ replaceVal(v, Valtype.f64);
329
+ push(v);
330
+ break;
331
+ }
332
+ case Opcodes.f64_trunc: {
333
+ if (stack.length < 1) { empty(); break; };
334
+ const v = Math.trunc(pop());
335
+
336
+ replaceVal(v, Valtype.f64);
337
+ push(v);
338
+ break;
339
+ }
340
+ case Opcodes.f64_nearest: {
341
+ if (stack.length < 1) { empty(); break; };
342
+ const v = Math.round(pop());
343
+
344
+ replaceVal(v, Valtype.f64);
345
+ push(v);
346
+ break;
347
+ }
348
+
349
+ case Opcodes.f64_sqrt: {
350
+ if (stack.length < 1) { empty(); break; };
351
+ const v = Math.sqrt(pop());
352
+
353
+ replaceVal(v, Valtype.f64);
354
+ push(v);
355
+ break;
356
+ }
357
+
358
+ case Opcodes.f64_add: {
359
+ if (stack.length < 2) { empty(); break; };
360
+ const [ b, a ] = pop2();
361
+ const v = a + b;
362
+
363
+ replaceVal(v, Valtype.f64);
364
+ push(v);
365
+ break;
366
+ }
367
+ case Opcodes.f64_sub: {
368
+ if (stack.length < 2) { empty(); break; };
369
+ const [ b, a ] = pop2();
370
+ const v = a - b;
371
+
372
+ replaceVal(v, Valtype.f64);
373
+ push(v);
374
+ break;
375
+ }
376
+ case Opcodes.f64_mul: {
377
+ if (stack.length < 2) { empty(); break; };
378
+ const [ b, a ] = pop2();
379
+ const v = a * b;
380
+
381
+ replaceVal(v, Valtype.f64);
382
+ push(v);
383
+ break;
384
+ }
385
+ case Opcodes.f64_div: {
386
+ if (stack.length < 2) { empty(); break; };
387
+ const [ b, a ] = pop2();
388
+ const v = a / b;
389
+
390
+ replaceVal(v, Valtype.f64);
391
+ push(v);
392
+ break;
393
+ }
394
+
395
+ case Opcodes.f64_min: {
396
+ if (stack.length < 2) { empty(); break; };
397
+ const [ b, a ] = pop2();
398
+ const v = Math.min(a, b);
399
+
400
+ replaceVal(v, Valtype.f64);
401
+ push(v);
402
+ break;
403
+ }
404
+ case Opcodes.f64_max: {
405
+ if (stack.length < 2) { empty(); break; };
406
+ const [ b, a ] = pop2();
407
+ const v = a + b;
408
+
409
+ replaceVal(v, Valtype.f64);
410
+ push(v);
411
+ break;
412
+ }
413
+
414
+ case Opcodes.f64_copysign: { // ?
415
+ if (stack.length < 2) { empty(); break; };
416
+ const [ b, a ] = pop2();
417
+ const v = Math.abs(a) * (b > 0 ? 1 : -1);
418
+
419
+ replaceVal(v, Valtype.f64);
420
+ push(v);
421
+ break;
422
+ }
423
+
424
+ case Opcodes.f64_convert_i32_u:
425
+ case Opcodes.f64_convert_i32_s: {
426
+ if (stack.length < 1) { empty(); break; };
427
+ const v = pop();
428
+
429
+ replaceVal(v, Valtype.f64);
430
+ push(v);
431
+ break;
432
+ }
433
+
434
+ case 0xfc02: { // i32_trunc_sat_f64_s
435
+ if (stack.length < 1) { empty(); break; }
436
+ const v = pop();
437
+
438
+ replaceVal(v, Valtype.i32);
439
+ push(v);
440
+ break;
441
+ }
442
+
443
+ case 0xfc03: { // i32_trunc_sat_f64_u
444
+ if (stack.length < 1) { empty(); break; }
445
+ const v = pop();
446
+
447
+ replaceVal(v, Valtype.i32);
448
+ push(v);
449
+ break;
450
+ }
451
+
452
+ default: {
453
+ empty();
454
+ break;
455
+ }
456
+ }
457
+
458
+ // this does, eg:
459
+ // local.get 7 ;; $i (i32)
460
+ // f64.convert_i32_s
461
+ // f64.const 1
462
+ // f64.add
463
+ // i32.trunc_sat_f64_s <--
464
+ // local.set 7 ;; $i (i32)
465
+ // ->
466
+ // local.get 7 ;; $i (i32)
467
+ // i32.const 1
468
+ // i32.add
469
+ // local.set 7 ;; $i (i32)
470
+ if (
471
+ (opcode >= 0xa0 && opcode <= 0xa3) || // main f64 math op
472
+ (opcode >= 0x61 && opcode <= 0x66) // main f64 eq op
473
+ ) {
474
+ const o2 = wasm[i - 1][0];
475
+ if (o2 === Opcodes.f64_const) { // f64.const
476
+ const o3 = wasm[i - 2][0];
477
+ if (o3 === Opcodes.f64_convert_i32_s || o3 === Opcodes.f64_convert_i32_u) {
478
+ // remove now unneeded i32 -> f64 convert
479
+ wasm.splice(i - 2, 1);
480
+ i--;
481
+
482
+ // convert f64.const -> i32.const
483
+ const n = read_ieee754_binary64(wasm[i - 1].slice(1));
484
+ wasm.splice(i - 1, 1, number(n, Valtype.i32));
485
+
486
+ // convert math op from f64 to i32
487
+ wasm[i][0] = f64ToI32Op[wasm[i][0]];
488
+
489
+ const nextOp = wasm[i + 1];
490
+ if (nextOp && opcode >= 0xa0 && opcode <= 0xa3) {
491
+ if (nextOp[0] === 0xfc && (nextOp[1] === 0x02 || nextOp[1] === 0x03)) {
492
+ // remove optional unneeded f64 -> i32 convert after
493
+ wasm.splice(i + 1, 1);
494
+ } else {
495
+ // add now needed i32 -> f64 convert after
496
+ wasm.splice(i + 1, Opcodes.i32_trunc_sat_f64_s);
497
+ }
498
+ }
499
+ }
500
+ }
501
+ }
502
+
503
+ if ((opcode === 0xfc02 || opcode === 0xfc03) && i > 3) { // i32.trunc_sat_f64_s/u
504
+ const o2 = wasm[i - 1][0];
505
+ if (
506
+ (o2 >= 0xa0 && o2 <= 0xa3) || // main f64 math op
507
+ (o2 >= 0x61 && o2 <= 0x66) // main f64 eq op
508
+ ) {
509
+ const o3 = wasm[i - 2][0];
510
+ if (o3 === Opcodes.f64_const) { // f64.const
511
+ const o4 = wasm[i - 3][0];
512
+ if (o4 === Opcodes.f64_convert_i32_s || o4 === Opcodes.f64_convert_i32_u) {
513
+ // remove now unneeded i32 -> f64 convert
514
+ wasm.splice(i - 3, 1);
515
+ i--;
516
+ } else {
517
+ // add now needed f64 -> i32 convert prior
518
+ wasm.splice(i - 2, 0, Opcodes.i32_trunc_sat_f64_s);
519
+ i++;
520
+ }
521
+
522
+ // convert f64.const -> i32.const
523
+ const n = read_ieee754_binary64(wasm[i - 2].slice(1));
524
+ wasm.splice(i - 2, 1, number(n, Valtype.i32));
525
+
526
+ // convert math op from f64 to i32
527
+ wasm[i - 1][0] = f64ToI32Op[wasm[i - 1][0]];
528
+
529
+ // remove this now unneeded f64 -> i32 convert
530
+ wasm.splice(i, 1);
531
+ }
532
+ }
533
+ }
534
+ }
535
+ };
@@ -4,6 +4,8 @@ import { read_ieee754_binary64, read_signedLEB128, read_unsignedLEB128 } from '.
4
4
  const inv = (obj, keyMap = x => x) => Object.keys(obj).reduce((acc, x) => { acc[keyMap(obj[x])] = x; return acc; }, {});
5
5
  const invOpcodes = inv(Opcodes);
6
6
  const invValtype = inv(Valtype);
7
+ globalThis.invOpcodes = invOpcodes;
8
+ globalThis.invValtype = invValtype;
7
9
 
8
10
  export default (wasm, name = '', ind = 0, locals = {}, params = [], returns = [], funcs = [], globals = {}, exceptions = []) => {
9
11
  const invLocals = inv(locals, x => x.idx);
@@ -91,7 +93,7 @@ export default (wasm, name = '', ind = 0, locals = {}, params = [], returns = []
91
93
  if (callFunc) out += ` ;; $${callFunc.name} ${makeSignature(callFunc.params, callFunc.returns)}`;
92
94
  if (globalThis.importFuncs && inst[1] < importFuncs.length) {
93
95
  const importFunc = importFuncs[inst[1]];
94
- out += ` ;; import ${importFunc.name} ${makeSignature(new Array(importFunc.params).fill(valtypeBinary), new Array(importFunc.returns).fill(valtypeBinary),)}`;
96
+ out += ` ;; import ${importFunc.name} ${makeSignature(typeof importFunc.params === 'object' ? importFunc.params : new Array(importFunc.params).fill(valtypeBinary), new Array(importFunc.returns).fill(valtypeBinary),)}`;
95
97
  }
96
98
  }
97
99
 
@@ -1748,7 +1748,7 @@ export const BuiltinFuncs = function() {
1748
1748
  localNames: ["iterable","iterable#type","out","type","forof_base_pointer","forof_length","forof_counter","x","x#type","#last_type","#typeswitch_tmp"],
1749
1749
  };
1750
1750
  this.__Set_prototype_union = {
1751
- wasm: (scope, {builtin,internalThrow,}) => [[32,2],[32,3],[16, builtin('__Porffor_rawType')],[68,0,0,0,0,0,0,52,64],[98],[4,64],...internalThrow(scope, 'TypeError', `Set.union requires 'Set'`),[11],[32,0],[65,20],[16, builtin('Set$constructor')],[33,4],[32,2],[252,3],[33,5],[65,0],[33,7],[32,5],[40,1,0],[33,6],[32,3],[33,11],[2,64],[32,11],[65,2],[70],[4,64,"TYPESWITCH|String"],[65,2],[33,9],[3,64],[65,0],[32,5],[47,0,4],[59,0,3],[68,0,0,0,0,0,0,240,191],[33,8],[2,64],[32,4],[65,20],[32,8],[32,9],[16, builtin('__Set_prototype_add')],[26],[26],[32,5],[65,2],[106],[33,5],[32,7],[65,1],[106],[34,7],[32,6],[71],[13,1],[11],[11],[12,1],[11],[32,11],[65,16],[70],[4,64,"TYPESWITCH|Array"],[3,64],[32,5],[43,0,4],[32,5],[45,0,12],[33,9],[33,8],[2,64],[32,4],[65,20],[32,8],[32,9],[16, builtin('__Set_prototype_add')],[26],[26],[32,5],[65,9],[106],[33,5],[32,7],[65,1],[106],[34,7],[32,6],[71],[13,1],[11],[11],[12,1],[11],[32,11],[65,18],[70],[4,64,"TYPESWITCH|ByteString"],[65,18],[33,9],[3,64],[65,0],[32,5],[32,7],[106],[45,0,4],[58,0,3],[68,0,0,0,0,0,0,240,191],[33,8],[2,64],[32,4],[65,20],[32,8],[32,9],[16, builtin('__Set_prototype_add')],[26],[26],[32,7],[65,1],[106],[34,7],[32,6],[71],[13,1],[11],[11],[12,1],[11],[32,11],[65,20],[70],[4,64,"TYPESWITCH|Set"],[3,64],[32,5],[43,0,4],[32,5],[45,0,12],[33,9],[33,8],[2,64],[32,4],[65,20],[32,8],[32,9],[16, builtin('__Set_prototype_add')],[26],[26],[32,5],[65,9],[106],[33,5],[32,7],[65,1],[106],[34,7],[32,6],[71],[13,1],[11],[11],[12,1],[11],...internalThrow(scope, 'TypeError', `Tried for..of on non-iterable type`),[11,"TYPESWITCH_end"],[32,4],[65,20],[15]],
1751
+ wasm: (scope, {builtin,internalThrow,}) => [[32,2],[32,3],[16, builtin('__Porffor_rawType')],[68,0,0,0,0,0,0,52,64],[98],[4,64],...internalThrow(scope, 'TypeError', `Set.prototype.union's 'other' argument must be a Set`),[11],[32,0],[65,20],[16, builtin('Set$constructor')],[33,4],[32,2],[252,3],[33,5],[65,0],[33,7],[32,5],[40,1,0],[33,6],[32,3],[33,11],[2,64],[32,11],[65,2],[70],[4,64,"TYPESWITCH|String"],[65,2],[33,9],[3,64],[65,0],[32,5],[47,0,4],[59,0,3],[68,0,0,0,0,0,0,240,191],[33,8],[2,64],[32,4],[65,20],[32,8],[32,9],[16, builtin('__Set_prototype_add')],[26],[26],[32,5],[65,2],[106],[33,5],[32,7],[65,1],[106],[34,7],[32,6],[71],[13,1],[11],[11],[12,1],[11],[32,11],[65,16],[70],[4,64,"TYPESWITCH|Array"],[3,64],[32,5],[43,0,4],[32,5],[45,0,12],[33,9],[33,8],[2,64],[32,4],[65,20],[32,8],[32,9],[16, builtin('__Set_prototype_add')],[26],[26],[32,5],[65,9],[106],[33,5],[32,7],[65,1],[106],[34,7],[32,6],[71],[13,1],[11],[11],[12,1],[11],[32,11],[65,18],[70],[4,64,"TYPESWITCH|ByteString"],[65,18],[33,9],[3,64],[65,0],[32,5],[32,7],[106],[45,0,4],[58,0,3],[68,0,0,0,0,0,0,240,191],[33,8],[2,64],[32,4],[65,20],[32,8],[32,9],[16, builtin('__Set_prototype_add')],[26],[26],[32,7],[65,1],[106],[34,7],[32,6],[71],[13,1],[11],[11],[12,1],[11],[32,11],[65,20],[70],[4,64,"TYPESWITCH|Set"],[3,64],[32,5],[43,0,4],[32,5],[45,0,12],[33,9],[33,8],[2,64],[32,4],[65,20],[32,8],[32,9],[16, builtin('__Set_prototype_add')],[26],[26],[32,5],[65,9],[106],[33,5],[32,7],[65,1],[106],[34,7],[32,6],[71],[13,1],[11],[11],[12,1],[11],...internalThrow(scope, 'TypeError', `Tried for..of on non-iterable type`),[11,"TYPESWITCH_end"],[32,4],[65,20],[15]],
1752
1752
  params: [124,127,124,127],
1753
1753
  typedParams: true,
1754
1754
  returns: [124,127],