porffor 0.0.0-650350
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +275 -0
- package/compiler/builtins/base64.js +92 -0
- package/compiler/builtins.js +770 -0
- package/compiler/codeGen.js +2027 -0
- package/compiler/decompile.js +102 -0
- package/compiler/embedding.js +19 -0
- package/compiler/encoding.js +217 -0
- package/compiler/expression.js +70 -0
- package/compiler/index.js +67 -0
- package/compiler/opt.js +436 -0
- package/compiler/parse.js +8 -0
- package/compiler/prototype.js +272 -0
- package/compiler/sections.js +154 -0
- package/compiler/wasmSpec.js +200 -0
- package/compiler/wrap.js +119 -0
- package/package.json +23 -0
- package/porf.cmd +2 -0
- package/publish.js +13 -0
- package/runner/compare.js +35 -0
- package/runner/index.js +34 -0
- package/runner/info.js +54 -0
- package/runner/profile.js +47 -0
- package/runner/repl.js +104 -0
- package/runner/sizes.js +38 -0
- package/runner/transform.js +36 -0
- package/sw.js +26 -0
- package/util/enum.js +20 -0
@@ -0,0 +1,102 @@
|
|
1
|
+
import { Blocktype, Opcodes, Valtype } from "./wasmSpec.js";
|
2
|
+
import { read_ieee754_binary64, read_signedLEB128, read_unsignedLEB128 } from "./encoding.js";
|
3
|
+
|
4
|
+
const inv = (obj, keyMap = x => x) => Object.keys(obj).reduce((acc, x) => { acc[keyMap(obj[x])] = x; return acc; }, {});
|
5
|
+
const invOpcodes = inv(Opcodes);
|
6
|
+
const invValtype = inv(Valtype);
|
7
|
+
|
8
|
+
export default (wasm, name = '', ind = 0, locals = {}, params = [], returns = [], funcs = [], globals = {}, exceptions = []) => {
|
9
|
+
const invLocals = inv(locals, x => x.idx);
|
10
|
+
const invGlobals = inv(globals, x => x.idx);
|
11
|
+
|
12
|
+
const makeSignature = (params, returns) => `(${params.map(x => invValtype[x]).join(', ')}) -> (${returns.map(x => invValtype[x]).join(', ')})`;
|
13
|
+
|
14
|
+
let out = '', depth = name ? 1 : 0;
|
15
|
+
if (name) out += `${makeSignature(params, returns)} ;; $${name} (${ind})\n`;
|
16
|
+
|
17
|
+
const justLocals = Object.values(locals).sort((a, b) => a.idx - b.idx).slice(params.length);
|
18
|
+
if (justLocals.length > 0) out += ` local ${justLocals.map(x => invValtype[x.type]).join(' ')}\n`;
|
19
|
+
|
20
|
+
let i = 0, lastInst;
|
21
|
+
for (let inst of wasm.concat(name ? [ [ Opcodes.end ] ] : [])) {
|
22
|
+
if (inst[0] === null) continue;
|
23
|
+
|
24
|
+
if (inst[0] === 0xfd) { // simd inst prefix
|
25
|
+
if (inst[1] >= 128) inst = [ [ inst[0], inst[1], inst[2] ], ...inst.slice(3) ];
|
26
|
+
else inst = [ [ inst[0], inst[1] ], ...inst.slice(2) ];
|
27
|
+
}
|
28
|
+
|
29
|
+
if (inst[0] === 0xfc) { // misc inst prefix
|
30
|
+
inst = [ [ inst[0], inst[1] ], ...inst.slice(2) ];
|
31
|
+
}
|
32
|
+
|
33
|
+
if (inst[0] === Opcodes.end || inst[0] === Opcodes.else || inst[0] === Opcodes.catch_all) depth--;
|
34
|
+
|
35
|
+
const opStr = invOpcodes[inst[0]];
|
36
|
+
if (!opStr) console.log(`decomp: unknown op ${inst[0].toString(16)}`)
|
37
|
+
out += /* ' '.repeat(3 - i.toString().length) + i + ' ' + */ ' '.repeat(Math.max(0, depth * 2)) + opStr.replace('_', '.').replace('return.', 'return_').replace('call.', 'call_').replace('br.', 'br_');
|
38
|
+
|
39
|
+
if (inst[0] === Opcodes.if || inst[0] === Opcodes.loop || inst[0] === Opcodes.block || inst[0] === Opcodes.else || inst[0] === Opcodes.try || inst[0] === Opcodes.catch_all) depth++;
|
40
|
+
|
41
|
+
if (inst[0] === Opcodes.f64_const) {
|
42
|
+
out += ` ${read_ieee754_binary64(inst.slice(1))}`;
|
43
|
+
} else if (inst[0] === Opcodes.i32_const || inst[0] === Opcodes.i64_const) {
|
44
|
+
out += ` ${read_signedLEB128(inst.slice(1))}`;
|
45
|
+
} else if (inst[0] === Opcodes.i32_load || inst[0] === Opcodes.i64_load || inst[0] === Opcodes.f64_load || inst[0] === Opcodes.i32_store || inst[0] === Opcodes.i64_store || inst[0] === Opcodes.f64_store) {
|
46
|
+
out += ` ${inst[1]} ${read_unsignedLEB128(inst.slice(2))}`
|
47
|
+
} else for (const operand of inst.slice(1)) {
|
48
|
+
if (inst[0] === Opcodes.if || inst[0] === Opcodes.loop || inst[0] === Opcodes.block) {
|
49
|
+
if (operand === Blocktype.void) continue;
|
50
|
+
out += ` ${invValtype[operand]}`;
|
51
|
+
} else {
|
52
|
+
out += ` ${operand}`;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
if (inst[0] === Opcodes.if || inst[0] === Opcodes.loop || inst[0] === Opcodes.block || inst[0] === Opcodes.else) {
|
57
|
+
out += ` ;; label @${depth}`;
|
58
|
+
}
|
59
|
+
|
60
|
+
if (inst[0] === Opcodes.br) {
|
61
|
+
out += ` ;; goto @${depth - inst[1]}`;
|
62
|
+
}
|
63
|
+
|
64
|
+
if (inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) {
|
65
|
+
const callFunc = funcs.find(x => x.index === inst[1]);
|
66
|
+
if (callFunc) out += ` ;; $${callFunc.name} ${makeSignature(callFunc.params, callFunc.returns)}`;
|
67
|
+
}
|
68
|
+
|
69
|
+
if (inst[0] === Opcodes.local_get || inst[0] === Opcodes.local_set || inst[0] === Opcodes.local_tee) {
|
70
|
+
const name = invLocals[inst[1]];
|
71
|
+
const type = invValtype[locals[name]?.type];
|
72
|
+
if (name) out += ` ;; $${name}${type !== valtype ? ` (${type})` : ''}`;
|
73
|
+
}
|
74
|
+
|
75
|
+
if (inst[0] === Opcodes.global_get || inst[0] === Opcodes.global_set) {
|
76
|
+
const name = invGlobals[inst[1]];
|
77
|
+
const type = invValtype[globals[name]?.type];
|
78
|
+
if (name) out += ` ;; $${name}${type !== valtype ? ` (${type})` : ''}`;
|
79
|
+
}
|
80
|
+
|
81
|
+
if (inst[0] === Opcodes.throw && lastInst && exceptions) {
|
82
|
+
const exception = exceptions[lastInst[1]];
|
83
|
+
if (exception) out += ` ;; ${exception.constructor ? `${exception.constructor}('${exception.message}')` : `'${exception.message}'`}`;
|
84
|
+
}
|
85
|
+
|
86
|
+
out += '\n';
|
87
|
+
lastInst = inst;
|
88
|
+
i++;
|
89
|
+
}
|
90
|
+
|
91
|
+
return highlightAsm(out);
|
92
|
+
};
|
93
|
+
|
94
|
+
export const highlightAsm = asm =>
|
95
|
+
asm
|
96
|
+
.replace(/(local|global|memory)\.[^\s]*/g, _ => `\x1B[31m${_}\x1B[0m`)
|
97
|
+
.replace(/(i(8|16|32|64)x[0-9]+|v128)(\.[^\s]*)?/g, _ => `\x1B[34m${_}\x1B[0m`)
|
98
|
+
.replace(/[^m](i32|i64|f32|f64)(\.[^\s]*)?/g, _ => `${_[0]}\x1B[36m${_.slice(1)}\x1B[0m`)
|
99
|
+
.replace(/(return_call|call|br_if|br|return|throw|rethrow)/g, _ => `\x1B[35m${_}\x1B[0m`)
|
100
|
+
.replace(/(block|loop|if|end|else|try|catch|catch_all|delegate)/g, _ => `\x1B[95m${_}\x1B[0m`)
|
101
|
+
.replace(/ \-?[0-9\.]+/g, _ => ` \x1B[33m${_.slice(1)}\x1B[0m`)
|
102
|
+
.replace(/ ;;.*$/gm, _ => `\x1B[90m${_.replaceAll(/\x1B\[[0-9]+m/g, '')}\x1B[0m`);
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import { Opcodes, Valtype } from "./wasmSpec.js";
|
2
|
+
import { signedLEB128, ieee754_binary64 } from "./encoding.js";
|
3
|
+
|
4
|
+
export const number = (n, valtype = valtypeBinary) => {
|
5
|
+
switch (valtype) {
|
6
|
+
case Valtype.i32: return [ [ Opcodes.i32_const, ...signedLEB128(n) ] ];
|
7
|
+
case Valtype.i64: return [ [ Opcodes.i64_const, ...signedLEB128(n) ] ];
|
8
|
+
case Valtype.f64: return [ [ Opcodes.f64_const, ...ieee754_binary64(n) ] ];
|
9
|
+
}
|
10
|
+
};
|
11
|
+
|
12
|
+
const enforceTwoBytes = arr => [ arr[0] ?? 0, arr[1] ?? 0, arr[2] ?? 0, arr[3] ?? 0 ];
|
13
|
+
export const i32x4 = (a, b, c, d) => [ [
|
14
|
+
...Opcodes.v128_const,
|
15
|
+
...enforceTwoBytes(signedLEB128(a)),
|
16
|
+
...enforceTwoBytes(signedLEB128(b)),
|
17
|
+
...enforceTwoBytes(signedLEB128(c)),
|
18
|
+
...enforceTwoBytes(signedLEB128(d))
|
19
|
+
] ];
|
@@ -0,0 +1,217 @@
|
|
1
|
+
export const codifyString = str => {
|
2
|
+
let out = [];
|
3
|
+
for (let i = 0; i < str.length; i++) {
|
4
|
+
out.push(str.charCodeAt(i));
|
5
|
+
}
|
6
|
+
|
7
|
+
return out;
|
8
|
+
};
|
9
|
+
|
10
|
+
export const encodeString = str => [
|
11
|
+
str.length,
|
12
|
+
...codifyString(str)
|
13
|
+
];
|
14
|
+
|
15
|
+
export const encodeVector = data => [
|
16
|
+
...unsignedLEB128(data.length),
|
17
|
+
...data.flat()
|
18
|
+
];
|
19
|
+
|
20
|
+
export const encodeLocal = (count, type) => [
|
21
|
+
...unsignedLEB128(count),
|
22
|
+
type
|
23
|
+
];
|
24
|
+
|
25
|
+
export const signedLEB128 = n => {
|
26
|
+
// todo: this only works with integers within 32 bit range
|
27
|
+
|
28
|
+
// just input for small numbers (for perf as common)
|
29
|
+
if (n >= 0 && n <= 63) return [ n ];
|
30
|
+
if (n >= -64 && n <= 0) return [ 128 + n ];
|
31
|
+
|
32
|
+
const buffer = [];
|
33
|
+
n |= 0;
|
34
|
+
|
35
|
+
while (true) {
|
36
|
+
let byte = n & 0x7f;
|
37
|
+
n >>= 7;
|
38
|
+
|
39
|
+
if ((n === 0 && (byte & 0x40) === 0) || (n === -1 && (byte & 0x40) !== 0)) {
|
40
|
+
buffer.push(byte);
|
41
|
+
break;
|
42
|
+
} else {
|
43
|
+
byte |= 0x80;
|
44
|
+
}
|
45
|
+
|
46
|
+
buffer.push(byte);
|
47
|
+
}
|
48
|
+
|
49
|
+
return buffer;
|
50
|
+
};
|
51
|
+
|
52
|
+
export const unsignedLEB128 = n => {
|
53
|
+
// just input for small numbers (for perf as common)
|
54
|
+
if (n >= 0 && n <= 127) return [ n ];
|
55
|
+
|
56
|
+
const buffer = [];
|
57
|
+
do {
|
58
|
+
let byte = n & 0x7f;
|
59
|
+
n >>>= 7;
|
60
|
+
if (n !== 0) {
|
61
|
+
byte |= 0x80;
|
62
|
+
}
|
63
|
+
buffer.push(byte);
|
64
|
+
} while (n !== 0);
|
65
|
+
return buffer;
|
66
|
+
};
|
67
|
+
|
68
|
+
export const read_signedLEB128 = _input => {
|
69
|
+
const input = [..._input];
|
70
|
+
let result = 0, shift = 0;
|
71
|
+
|
72
|
+
while (true) {
|
73
|
+
const byte = input.shift();
|
74
|
+
result |= (byte & 0x7f) << shift;
|
75
|
+
|
76
|
+
shift += 7;
|
77
|
+
|
78
|
+
if ((0x80 & byte) === 0) {
|
79
|
+
if (shift < 32 && (byte & 0x40) !== 0) {
|
80
|
+
return result | (-1 << shift);
|
81
|
+
}
|
82
|
+
|
83
|
+
return result;
|
84
|
+
}
|
85
|
+
}
|
86
|
+
};
|
87
|
+
|
88
|
+
// todo: check this with large unsigned values
|
89
|
+
export const read_unsignedLEB128 = _input => {
|
90
|
+
const input = [..._input];
|
91
|
+
let result = 0, shift = 0;
|
92
|
+
|
93
|
+
while (true) {
|
94
|
+
const byte = input.shift();
|
95
|
+
result |= (byte & 0x7f) << shift;
|
96
|
+
|
97
|
+
shift += 7;
|
98
|
+
|
99
|
+
if ((0x80 & byte) === 0) {
|
100
|
+
return result;
|
101
|
+
}
|
102
|
+
}
|
103
|
+
};
|
104
|
+
|
105
|
+
// ieee 754 binary64
|
106
|
+
|
107
|
+
// from https://github.com/feross/ieee754
|
108
|
+
// BSD 3-Clause. Copyright 2008 Fair Oaks Labs, Inc. (https://github.com/feross/ieee754/blob/master/LICENSE)
|
109
|
+
export const ieee754_binary64 = value => {
|
110
|
+
let isLE = true, mLen = 52, nBytes = 8, offset = 0;
|
111
|
+
let buffer = new Array(nBytes).fill(0);
|
112
|
+
|
113
|
+
let e, m, c
|
114
|
+
let eLen = (nBytes * 8) - mLen - 1
|
115
|
+
const eMax = (1 << eLen) - 1
|
116
|
+
const eBias = eMax >> 1
|
117
|
+
const rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
|
118
|
+
let i = isLE ? 0 : (nBytes - 1)
|
119
|
+
const d = isLE ? 1 : -1
|
120
|
+
const s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
|
121
|
+
|
122
|
+
value = Math.abs(value)
|
123
|
+
|
124
|
+
if (isNaN(value) || value === Infinity) {
|
125
|
+
m = isNaN(value) ? 1 : 0
|
126
|
+
e = eMax
|
127
|
+
} else {
|
128
|
+
e = Math.floor(Math.log(value) / Math.LN2)
|
129
|
+
if (value * (c = Math.pow(2, -e)) < 1) {
|
130
|
+
e--
|
131
|
+
c *= 2
|
132
|
+
}
|
133
|
+
if (e + eBias >= 1) {
|
134
|
+
value += rt / c
|
135
|
+
} else {
|
136
|
+
value += rt * Math.pow(2, 1 - eBias)
|
137
|
+
}
|
138
|
+
if (value * c >= 2) {
|
139
|
+
e++
|
140
|
+
c /= 2
|
141
|
+
}
|
142
|
+
|
143
|
+
if (e + eBias >= eMax) {
|
144
|
+
m = 0
|
145
|
+
e = eMax
|
146
|
+
} else if (e + eBias >= 1) {
|
147
|
+
m = ((value * c) - 1) * Math.pow(2, mLen)
|
148
|
+
e = e + eBias
|
149
|
+
} else {
|
150
|
+
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
|
151
|
+
e = 0
|
152
|
+
}
|
153
|
+
}
|
154
|
+
|
155
|
+
while (mLen >= 8) {
|
156
|
+
buffer[offset + i] = m & 0xff
|
157
|
+
i += d
|
158
|
+
m /= 256
|
159
|
+
mLen -= 8
|
160
|
+
}
|
161
|
+
|
162
|
+
e = (e << mLen) | m
|
163
|
+
eLen += mLen
|
164
|
+
while (eLen > 0) {
|
165
|
+
buffer[offset + i] = e & 0xff
|
166
|
+
i += d
|
167
|
+
e /= 256
|
168
|
+
eLen -= 8
|
169
|
+
}
|
170
|
+
|
171
|
+
buffer[offset + i - d] |= s * 128
|
172
|
+
|
173
|
+
return buffer;
|
174
|
+
};
|
175
|
+
|
176
|
+
export const read_ieee754_binary64 = buffer => {
|
177
|
+
let isLE = true, mLen = 52, nBytes = 8, offset = 0;
|
178
|
+
|
179
|
+
let e, m
|
180
|
+
const eLen = (nBytes * 8) - mLen - 1
|
181
|
+
const eMax = (1 << eLen) - 1
|
182
|
+
const eBias = eMax >> 1
|
183
|
+
let nBits = -7
|
184
|
+
let i = isLE ? (nBytes - 1) : 0
|
185
|
+
const d = isLE ? -1 : 1
|
186
|
+
let s = buffer[offset + i]
|
187
|
+
|
188
|
+
i += d
|
189
|
+
|
190
|
+
e = s & ((1 << (-nBits)) - 1)
|
191
|
+
s >>= (-nBits)
|
192
|
+
nBits += eLen
|
193
|
+
while (nBits > 0) {
|
194
|
+
e = (e * 256) + buffer[offset + i]
|
195
|
+
i += d
|
196
|
+
nBits -= 8
|
197
|
+
}
|
198
|
+
|
199
|
+
m = e & ((1 << (-nBits)) - 1)
|
200
|
+
e >>= (-nBits)
|
201
|
+
nBits += mLen
|
202
|
+
while (nBits > 0) {
|
203
|
+
m = (m * 256) + buffer[offset + i]
|
204
|
+
i += d
|
205
|
+
nBits -= 8
|
206
|
+
}
|
207
|
+
|
208
|
+
if (e === 0) {
|
209
|
+
e = 1 - eBias
|
210
|
+
} else if (e === eMax) {
|
211
|
+
return m ? NaN : ((s ? -1 : 1) * Infinity)
|
212
|
+
} else {
|
213
|
+
m = m + Math.pow(2, mLen)
|
214
|
+
e = e - eBias
|
215
|
+
}
|
216
|
+
return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
|
217
|
+
};
|
@@ -0,0 +1,70 @@
|
|
1
|
+
import { Opcodes } from "./wasmSpec.js";
|
2
|
+
|
3
|
+
export const operatorOpcode = {
|
4
|
+
i32: {
|
5
|
+
'+': Opcodes.i32_add,
|
6
|
+
'-': Opcodes.i32_sub,
|
7
|
+
'*': Opcodes.i32_mul,
|
8
|
+
'/': Opcodes.i32_div_s,
|
9
|
+
'%': Opcodes.i32_rem_s,
|
10
|
+
|
11
|
+
'&': Opcodes.i32_and,
|
12
|
+
'|': Opcodes.i32_or,
|
13
|
+
'^': Opcodes.i32_xor,
|
14
|
+
'<<': Opcodes.i32_shl,
|
15
|
+
'>>': Opcodes.i32_shr_s,
|
16
|
+
'>>>': Opcodes.i32_shr_u,
|
17
|
+
|
18
|
+
'==': Opcodes.i32_eq,
|
19
|
+
'===': Opcodes.i32_eq,
|
20
|
+
'!=': Opcodes.i32_ne,
|
21
|
+
'!==': Opcodes.i32_ne,
|
22
|
+
|
23
|
+
'>': Opcodes.i32_gt_s,
|
24
|
+
'>=': Opcodes.i32_ge_s,
|
25
|
+
'<': Opcodes.i32_lt_s,
|
26
|
+
'<=': Opcodes.i32_le_s
|
27
|
+
},
|
28
|
+
|
29
|
+
i64: {
|
30
|
+
'+': Opcodes.i64_add,
|
31
|
+
'-': Opcodes.i64_sub,
|
32
|
+
'*': Opcodes.i64_mul,
|
33
|
+
'/': Opcodes.i64_div_s,
|
34
|
+
'%': Opcodes.i64_rem_s,
|
35
|
+
|
36
|
+
'&': Opcodes.i64_and,
|
37
|
+
'|': Opcodes.i64_or,
|
38
|
+
'^': Opcodes.i64_xor,
|
39
|
+
'<<': Opcodes.i64_shl,
|
40
|
+
'>>': Opcodes.i64_shr_s,
|
41
|
+
'>>>': Opcodes.i64_shr_u,
|
42
|
+
|
43
|
+
'==': Opcodes.i64_eq,
|
44
|
+
'===': Opcodes.i64_eq,
|
45
|
+
'!=': Opcodes.i64_ne,
|
46
|
+
'!==': Opcodes.i64_ne,
|
47
|
+
|
48
|
+
'>': Opcodes.i64_gt_s,
|
49
|
+
'>=': Opcodes.i64_ge_s,
|
50
|
+
'<': Opcodes.i64_lt_s,
|
51
|
+
'<=': Opcodes.i64_le_s
|
52
|
+
},
|
53
|
+
|
54
|
+
f64: {
|
55
|
+
'+': Opcodes.f64_add,
|
56
|
+
'-': Opcodes.f64_sub,
|
57
|
+
'*': Opcodes.f64_mul,
|
58
|
+
'/': Opcodes.f64_div,
|
59
|
+
|
60
|
+
'==': Opcodes.f64_eq,
|
61
|
+
'===': Opcodes.f64_eq,
|
62
|
+
'!=': Opcodes.f64_ne,
|
63
|
+
'!==': Opcodes.f64_ne,
|
64
|
+
|
65
|
+
'>': Opcodes.f64_gt,
|
66
|
+
'>=': Opcodes.f64_ge,
|
67
|
+
'<': Opcodes.f64_lt,
|
68
|
+
'<=': Opcodes.f64_le
|
69
|
+
}
|
70
|
+
};
|
@@ -0,0 +1,67 @@
|
|
1
|
+
import parse from './parse.js';
|
2
|
+
import codeGen from './codeGen.js';
|
3
|
+
import opt from './opt.js';
|
4
|
+
import produceSections from './sections.js';
|
5
|
+
import decompile from './decompile.js';
|
6
|
+
import { BuiltinPreludes } from './builtins.js';
|
7
|
+
|
8
|
+
globalThis.decompile = decompile;
|
9
|
+
|
10
|
+
const rgb = (r, g, b, x) => `\x1b[38;2;${r};${g};${b}m${x}\u001b[0m`;
|
11
|
+
const underline = x => `\u001b[4m${x}\u001b[0m`;
|
12
|
+
const bold = x => `\u001b[1m${x}\u001b[0m`;
|
13
|
+
|
14
|
+
const areaColors = {
|
15
|
+
codegen: [ 20, 80, 250 ],
|
16
|
+
opt: [ 250, 20, 80 ],
|
17
|
+
sections: [ 20, 250, 80 ]
|
18
|
+
};
|
19
|
+
|
20
|
+
globalThis.log = (area, ...args) => console.log(`\u001b[90m[\u001b[0m${rgb(...areaColors[area], area)}\u001b[90m]\u001b[0m`, ...args);
|
21
|
+
|
22
|
+
const logFuncs = (funcs, globals, exceptions) => {
|
23
|
+
console.log('\n' + underline(bold('funcs')));
|
24
|
+
|
25
|
+
for (const f of funcs) {
|
26
|
+
console.log(`${underline(f.name)} (${f.index})`);
|
27
|
+
|
28
|
+
console.log(`params: ${f.params.map((_, i) => Object.keys(f.locals)[Object.values(f.locals).indexOf(Object.values(f.locals).find(x => x.idx === i))]).join(', ')}`);
|
29
|
+
console.log(`returns: ${f.returns.length > 0 ? true : false}`);
|
30
|
+
console.log(`locals: ${Object.keys(f.locals).sort((a, b) => f.locals[a].idx - f.locals[b].idx).map(x => `${x} (${f.locals[x].idx})`).join(', ')}`);
|
31
|
+
console.log();
|
32
|
+
console.log(decompile(f.wasm, f.name, f.index, f.locals, f.params, f.returns, funcs, globals, exceptions));
|
33
|
+
}
|
34
|
+
|
35
|
+
console.log();
|
36
|
+
};
|
37
|
+
|
38
|
+
export default (code, flags) => {
|
39
|
+
globalThis.optLog = process.argv.includes('-opt-log');
|
40
|
+
globalThis.codeLog = process.argv.includes('-code-log');
|
41
|
+
|
42
|
+
for (const x in BuiltinPreludes) {
|
43
|
+
if (code.indexOf(x + '(') !== -1) code = BuiltinPreludes[x] + code;
|
44
|
+
}
|
45
|
+
|
46
|
+
const t0 = performance.now();
|
47
|
+
const program = parse(code, flags);
|
48
|
+
if (flags.includes('info')) console.log(`1. parsed in ${(performance.now() - t0).toFixed(2)}ms`);
|
49
|
+
|
50
|
+
const t1 = performance.now();
|
51
|
+
const { funcs, globals, tags, exceptions, pages } = codeGen(program);
|
52
|
+
if (flags.includes('info')) console.log(`2. generated code in ${(performance.now() - t1).toFixed(2)}ms`);
|
53
|
+
|
54
|
+
if (process.argv.includes('-funcs')) logFuncs(funcs, globals, exceptions);
|
55
|
+
|
56
|
+
const t2 = performance.now();
|
57
|
+
opt(funcs, globals);
|
58
|
+
if (flags.includes('info')) console.log(`3. optimized code in ${(performance.now() - t2).toFixed(2)}ms`);
|
59
|
+
|
60
|
+
if (process.argv.includes('-opt-funcs')) logFuncs(funcs, globals, exceptions);
|
61
|
+
|
62
|
+
const t3 = performance.now();
|
63
|
+
const sections = produceSections(funcs, globals, tags, pages, flags);
|
64
|
+
if (flags.includes('info')) console.log(`4. produced sections in ${(performance.now() - t3).toFixed(2)}ms`);
|
65
|
+
|
66
|
+
return { wasm: sections, funcs, globals, tags, exceptions, pages };
|
67
|
+
};
|