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.
- package/compiler/2c.js +53 -65
- package/compiler/assemble.js +5 -4
- package/compiler/builtins/porffor.d.ts +3 -0
- package/compiler/builtins.js +25 -5
- package/compiler/codegen.js +13 -32
- package/compiler/cyclone.js +535 -0
- package/compiler/decompile.js +3 -1
- package/compiler/generated_builtins.js +1 -1
- package/compiler/havoc.js +93 -0
- package/compiler/index.js +76 -6
- package/compiler/opt.js +3 -39
- package/compiler/pgo.js +207 -0
- package/compiler/prefs.js +6 -1
- package/compiler/wrap.js +53 -12
- package/no_pgo.txt +923 -0
- package/package.json +1 -1
- package/pgo.txt +916 -0
- package/runner/index.js +13 -8
- /package/runner/{profiler.js → profile.js} +0 -0
package/compiler/codegen.js
CHANGED
@@ -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
|
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:
|
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 = (
|
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
|
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,
|
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
|
+
};
|
package/compiler/decompile.js
CHANGED
@@ -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
|
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],
|