porffor 0.2.0-fde989a → 0.14.0-4057a18e9
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/CONTRIBUTING.md +256 -0
- package/LICENSE +20 -20
- package/README.md +131 -86
- package/asur/README.md +2 -0
- package/asur/index.js +1262 -0
- package/byg/index.js +216 -0
- package/compiler/2c.js +2 -53
- package/compiler/{sections.js → assemble.js} +84 -21
- package/compiler/builtins/annexb_string.js +72 -0
- package/compiler/builtins/annexb_string.ts +18 -0
- package/compiler/builtins/array.ts +145 -0
- package/compiler/builtins/base64.ts +76 -0
- package/compiler/builtins/boolean.ts +18 -0
- package/compiler/builtins/crypto.ts +120 -0
- package/compiler/builtins/date.ts +2067 -0
- package/compiler/builtins/escape.ts +141 -0
- package/compiler/builtins/function.ts +5 -0
- package/compiler/builtins/int.ts +145 -0
- package/compiler/builtins/number.ts +529 -0
- package/compiler/builtins/object.ts +4 -0
- package/compiler/builtins/porffor.d.ts +60 -0
- package/compiler/builtins/set.ts +187 -0
- package/compiler/builtins/string.ts +1080 -0
- package/compiler/builtins.js +436 -283
- package/compiler/{codeGen.js → codegen.js} +1027 -482
- package/compiler/decompile.js +2 -3
- package/compiler/embedding.js +22 -22
- package/compiler/encoding.js +94 -10
- package/compiler/expression.js +1 -1
- package/compiler/generated_builtins.js +1625 -0
- package/compiler/index.js +25 -36
- package/compiler/log.js +6 -3
- package/compiler/opt.js +55 -41
- package/compiler/parse.js +38 -30
- package/compiler/precompile.js +120 -0
- package/compiler/prefs.js +27 -0
- package/compiler/prototype.js +31 -46
- package/compiler/types.js +38 -0
- package/compiler/wasmSpec.js +33 -8
- package/compiler/wrap.js +88 -70
- package/package.json +9 -5
- package/porf +2 -0
- package/rhemyn/compile.js +46 -27
- package/rhemyn/parse.js +322 -320
- package/rhemyn/test/parse.js +58 -58
- package/runner/compare.js +33 -34
- package/runner/debug.js +117 -0
- package/runner/index.js +78 -11
- package/runner/profiler.js +75 -0
- package/runner/repl.js +40 -13
- package/runner/sizes.js +37 -37
- package/runner/version.js +10 -8
- package/compiler/builtins/base64.js +0 -92
- package/filesize.cmd +0 -2
- package/runner/info.js +0 -89
- package/runner/profile.js +0 -46
- package/runner/results.json +0 -1
- package/runner/transform.js +0 -15
- package/tmp.c +0 -661
- package/util/enum.js +0 -20
package/byg/index.js
ADDED
@@ -0,0 +1,216 @@
|
|
1
|
+
import fs from 'node:fs';
|
2
|
+
|
3
|
+
const noAnsi = s => s.replace(/\u001b\[[0-9]+m/g, '');
|
4
|
+
const printLine = (line, number, breakpoint = false, current = false, selected = false) => {
|
5
|
+
console.log(`\x1b[${breakpoint ? (selected ? '43' : '103') : (selected ? '47' : '100')}m\x1b[${selected || breakpoint ? '30' : '97'}m${number.toFixed(0).padStart(4, ' ')}\x1b[${breakpoint ? (selected ? '33' : '93') : (selected ? '37' : '90')}m\x1b[${current ? '47' : '40'}m▌ \x1b[${current ? '47' : '40'}m\x1b[${current ? '30' : '37'}m${current ? noAnsi(line) : line}\x1b[0K`);
|
6
|
+
};
|
7
|
+
|
8
|
+
const box = (x, y, width, height, title = '', content = [], color = ['90', '100', '37', '35', '45'], padding = true) => {
|
9
|
+
if (padding) {
|
10
|
+
width += 1;
|
11
|
+
height += 1;
|
12
|
+
|
13
|
+
// top
|
14
|
+
process.stdout.write(`\x1b[48m\x1b[${y + 1};${x + 1}H\x1b[${color[0]}m` + '▄'.repeat(width));
|
15
|
+
// bottom
|
16
|
+
process.stdout.write(`\x1b[${y + height + 1};${x + 1}H▝` + '▀'.repeat(width - 1) + '▘');
|
17
|
+
// left
|
18
|
+
process.stdout.write(`\x1b[${y + 1};${x + 1}H▗` + '\x1b[1B\x1b[1D▐'.repeat(height - 1));
|
19
|
+
// right
|
20
|
+
process.stdout.write(`\x1b[${y + 1};${x + width + 1}H▖` + '\x1b[1B\x1b[1D▌'.repeat(height - 1));
|
21
|
+
|
22
|
+
x += 1;
|
23
|
+
y += 1;
|
24
|
+
width -= 1;
|
25
|
+
height -= 1;
|
26
|
+
}
|
27
|
+
|
28
|
+
// bg
|
29
|
+
process.stdout.write(`\x1b[${y + 1};${x + 1}H\x1b[${color[1]}m` + ' '.repeat(width) + (`\x1b[1B\x1b[${width}D` + ' '.repeat(width)).repeat(Math.max(0, height - 1)));
|
30
|
+
|
31
|
+
// title
|
32
|
+
if (title) process.stdout.write(`\x1b[${y};${x}H\x1b[0m\x1b[${color[3]}m▐\x1b[${color[4]}m\x1b[${color[2]}m\x1b[1m${' '.repeat((width - title.length) / 2 | 0)}${title}${' '.repeat(width - (((width - title.length) / 2 | 0)) - title.length)}\x1b[0m\x1b[${color[3]}m▌`);
|
33
|
+
|
34
|
+
// content
|
35
|
+
process.stdout.write(`\x1b[${y + (title ? 1 : 1)};${x + 1}H\x1b[${color[1]}m\x1b[${color[2]}m${content.join(`\x1b[1B\x1b[${x + 1}G`)}`);
|
36
|
+
};
|
37
|
+
|
38
|
+
const controls = {
|
39
|
+
'ret': 'resume ',
|
40
|
+
'b': 'breakpoint ',
|
41
|
+
's': 'step over',
|
42
|
+
'i': 'step in',
|
43
|
+
'o': 'step out ',
|
44
|
+
};
|
45
|
+
|
46
|
+
const controlInfo = Object.keys(controls).reduce((acc, x, i) => acc + `\x1B[45m\x1B[97m${x}\x1b[105m\x1b[37m ${controls[x]} `, '');
|
47
|
+
const plainControlInfo = noAnsi(controlInfo);
|
48
|
+
|
49
|
+
globalThis.termWidth = process.stdout.columns || 80;
|
50
|
+
globalThis.termHeight = process.stdout.rows || 24;
|
51
|
+
|
52
|
+
export default ({ lines, pause, breakpoint }) => {
|
53
|
+
process.stdin.setRawMode(true);
|
54
|
+
process.stdin.resume();
|
55
|
+
process.stdin.setEncoding('utf8');
|
56
|
+
|
57
|
+
process.stdin.on('data', s => {
|
58
|
+
// ctrl c
|
59
|
+
if (s === '\u0003') {
|
60
|
+
process.exit();
|
61
|
+
}
|
62
|
+
|
63
|
+
if (!paused) pause();
|
64
|
+
});
|
65
|
+
|
66
|
+
const stdin = fs.openSync('/dev/stdin', 'r+');
|
67
|
+
const readCharSync = () => {
|
68
|
+
const buffer = Buffer.alloc(1);
|
69
|
+
fs.readSync(stdin, buffer, 0, 1);
|
70
|
+
return buffer.toString('utf8');
|
71
|
+
};
|
72
|
+
|
73
|
+
const tooManyLines = lines.length > (termHeight - 1);
|
74
|
+
const breakpoints = {};
|
75
|
+
|
76
|
+
process.on('exit', () => {
|
77
|
+
process.stdout.write('\x1b[0m');
|
78
|
+
});
|
79
|
+
|
80
|
+
console.clear();
|
81
|
+
|
82
|
+
let paused = true;
|
83
|
+
return (_paused, currentLine, text, boxes = []) => {
|
84
|
+
paused = _paused;
|
85
|
+
|
86
|
+
let scrollOffset = 0;
|
87
|
+
let currentLinePos = currentLine;
|
88
|
+
|
89
|
+
const draw = () => {
|
90
|
+
console.clear();
|
91
|
+
process.stdout.write(`\x1b[1;1H`);
|
92
|
+
|
93
|
+
if (tooManyLines) {
|
94
|
+
const edgePadding = (termHeight / 2) - 1;
|
95
|
+
let beforePadding = currentLine - edgePadding;
|
96
|
+
let afterPadding = currentLine + edgePadding + 1;
|
97
|
+
|
98
|
+
if (beforePadding < 0) {
|
99
|
+
afterPadding += Math.abs(beforePadding);
|
100
|
+
beforePadding = 0;
|
101
|
+
}
|
102
|
+
|
103
|
+
beforePadding += scrollOffset;
|
104
|
+
afterPadding += scrollOffset;
|
105
|
+
|
106
|
+
if (afterPadding > lines.length) {
|
107
|
+
beforePadding -= afterPadding - lines.length;
|
108
|
+
afterPadding = lines.length;
|
109
|
+
}
|
110
|
+
|
111
|
+
for (let i = Math.max(0, beforePadding); i < Math.max(0, beforePadding) + (termHeight - 1); i++) {
|
112
|
+
printLine(lines[i], i + 1, !!breakpoints[i], currentLine === i, currentLine + scrollOffset === i);
|
113
|
+
}
|
114
|
+
|
115
|
+
currentLinePos = currentLine - beforePadding;
|
116
|
+
} else {
|
117
|
+
for (let i = 0; i < lines.length; i++) {
|
118
|
+
printLine(lines[i], i + 1, !!breakpoints[i], currentLine === i, currentLine + scrollOffset === i);
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
for (const x of boxes) {
|
123
|
+
const y = x.y({ currentLinePos });
|
124
|
+
if (y < 0 || y >= termHeight) continue;
|
125
|
+
|
126
|
+
box(x.x, y, x.width, x.height, x.title, x.content);
|
127
|
+
}
|
128
|
+
|
129
|
+
// text += ` | rss: ${(process.memoryUsage.rss() / 1024 / 1024).toFixed(2)}mb`;
|
130
|
+
|
131
|
+
process.stdout.write(`\x1b[${termHeight};1H\x1b[105m\x1b[37m${text}${' '.repeat(termWidth - plainControlInfo.length - noAnsi(text).length - 1)}${controlInfo} \x1b[0m`);
|
132
|
+
};
|
133
|
+
|
134
|
+
draw();
|
135
|
+
|
136
|
+
let lastSpecial = false;
|
137
|
+
while (true) {
|
138
|
+
const char = readCharSync();
|
139
|
+
|
140
|
+
if (char === '[') {
|
141
|
+
lastSpecial = true;
|
142
|
+
continue;
|
143
|
+
}
|
144
|
+
|
145
|
+
switch (char.toLowerCase()) {
|
146
|
+
case '\r': {
|
147
|
+
paused = false;
|
148
|
+
return 'resume';
|
149
|
+
}
|
150
|
+
|
151
|
+
case 's': {
|
152
|
+
return 'stepOver';
|
153
|
+
}
|
154
|
+
|
155
|
+
case 'i': {
|
156
|
+
return 'stepIn';
|
157
|
+
}
|
158
|
+
|
159
|
+
case 'o': {
|
160
|
+
return 'stepOut';
|
161
|
+
}
|
162
|
+
|
163
|
+
case 'b': {
|
164
|
+
if (!lastSpecial) {
|
165
|
+
// b pressed normally
|
166
|
+
breakpoints[currentLine + scrollOffset] = !breakpoints[currentLine + scrollOffset];
|
167
|
+
draw();
|
168
|
+
|
169
|
+
breakpoint(currentLine + scrollOffset, breakpoints[currentLine + scrollOffset]);
|
170
|
+
break;
|
171
|
+
}
|
172
|
+
|
173
|
+
// arrow down
|
174
|
+
if (scrollOffset < lines.length - currentLine - 1) scrollOffset++;
|
175
|
+
draw();
|
176
|
+
break;
|
177
|
+
}
|
178
|
+
|
179
|
+
case 'a': {
|
180
|
+
if (!lastSpecial) break;
|
181
|
+
|
182
|
+
// arrow up
|
183
|
+
if (scrollOffset > -currentLine) scrollOffset--;
|
184
|
+
draw();
|
185
|
+
|
186
|
+
break;
|
187
|
+
}
|
188
|
+
|
189
|
+
case '5': {
|
190
|
+
if (!lastSpecial) break;
|
191
|
+
|
192
|
+
// page up
|
193
|
+
scrollOffset -= Math.min(scrollOffset + currentLine, termHeight - 1);
|
194
|
+
draw();
|
195
|
+
break;
|
196
|
+
}
|
197
|
+
|
198
|
+
case '6': {
|
199
|
+
if (!lastSpecial) break;
|
200
|
+
|
201
|
+
// page down
|
202
|
+
scrollOffset += Math.min(lines.length - (scrollOffset + currentLine) - 1, termHeight - 1);
|
203
|
+
draw();
|
204
|
+
break;
|
205
|
+
}
|
206
|
+
|
207
|
+
case 'q':
|
208
|
+
case '\u0003': {
|
209
|
+
process.exit();
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
lastSpecial = false;
|
214
|
+
}
|
215
|
+
};
|
216
|
+
};
|
package/compiler/2c.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import { read_ieee754_binary64, read_signedLEB128, read_unsignedLEB128 } from './encoding.js';
|
2
2
|
import { Blocktype, Opcodes, Valtype } from './wasmSpec.js';
|
3
3
|
import { operatorOpcode } from './expression.js';
|
4
|
-
import { log } from
|
4
|
+
import { log } from './log.js';
|
5
5
|
|
6
6
|
const CValtype = {
|
7
7
|
i8: 'i8',
|
@@ -106,17 +106,6 @@ for (const x in CValtype) {
|
|
106
106
|
if (Valtype[x]) CValtype[Valtype[x]] = CValtype[x];
|
107
107
|
}
|
108
108
|
|
109
|
-
const todo = msg => {
|
110
|
-
class TodoError extends Error {
|
111
|
-
constructor(message) {
|
112
|
-
super(message);
|
113
|
-
this.name = 'TodoError';
|
114
|
-
}
|
115
|
-
}
|
116
|
-
|
117
|
-
throw new TodoError(`todo: ${msg}`);
|
118
|
-
};
|
119
|
-
|
120
109
|
const removeBrackets = str => {
|
121
110
|
// return str;
|
122
111
|
// if (str.startsWith(`(${CValtype.i32})(${CValtype.u32})`)) return `(${CValtype.i32})(${CValtype.u32})(` + removeBrackets(str.slice(22, -1)) + ')';
|
@@ -167,11 +156,6 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
167
156
|
prependMain.set('_data', data.map(x => `memcpy(_memory + ${x.offset}, (unsigned char[]){${x.bytes.join(',')}}, ${x.bytes.length});`).join('\n'));
|
168
157
|
}
|
169
158
|
|
170
|
-
// for (const [ x, p ] of pages) {
|
171
|
-
// out += `${CValtype[p.type]} ${x.replace(': ', '_').replace(/[^0-9a-zA-Z_]/g, '')}[100]`;
|
172
|
-
// out += ';\n';
|
173
|
-
// }
|
174
|
-
|
175
159
|
if (out) out += '\n';
|
176
160
|
|
177
161
|
let depth = 1;
|
@@ -213,9 +197,9 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
213
197
|
|
214
198
|
for (const f of funcs) {
|
215
199
|
depth = 1;
|
200
|
+
brDepth = 0;
|
216
201
|
|
217
202
|
const invLocals = inv(f.locals, x => x.idx);
|
218
|
-
// if (f.returns.length > 1) todo('funcs returning >1 value unsupported');
|
219
203
|
|
220
204
|
for (const x in invLocals) {
|
221
205
|
invLocals[x] = sanitize(invLocals[x]);
|
@@ -247,12 +231,7 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
247
231
|
const brs = [];
|
248
232
|
let lastCond = false;
|
249
233
|
|
250
|
-
// let brDepth = 0;
|
251
|
-
|
252
234
|
const blockStart = (i, loop) => {
|
253
|
-
// reset "stack"
|
254
|
-
// vals = [];
|
255
|
-
|
256
235
|
rets.push(i[1]);
|
257
236
|
|
258
237
|
const br = brId++;
|
@@ -269,25 +248,6 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
269
248
|
brDepth++;
|
270
249
|
};
|
271
250
|
|
272
|
-
const highlight = i => {
|
273
|
-
const surrounding = 6;
|
274
|
-
|
275
|
-
const decomp = decompile(f.wasm.slice(i - surrounding, i + surrounding + 1), '', 0, f.locals, f.params, f.returns, funcs, globals, exceptions).slice(0, -1).split('\n');
|
276
|
-
|
277
|
-
const noAnsi = s => s.replace(/\u001b\[[0-9]+m/g, '');
|
278
|
-
let longest = 0;
|
279
|
-
for (let j = 0; j < decomp.length; j++) {
|
280
|
-
longest = Math.max(longest, noAnsi(decomp[j]).length);
|
281
|
-
}
|
282
|
-
|
283
|
-
const middle = Math.floor(decomp.length / 2);
|
284
|
-
decomp[middle] = `\x1B[47m\x1B[30m${noAnsi(decomp[middle])}${'\u00a0'.repeat(longest - noAnsi(decomp[middle]).length)}\x1B[0m`;
|
285
|
-
|
286
|
-
console.log('\x1B[90m...\x1B[0m');
|
287
|
-
console.log(decomp.join('\n'));
|
288
|
-
console.log('\x1B[90m...\x1B[0m\n');
|
289
|
-
};
|
290
|
-
|
291
251
|
for (let _ = 0; _ < f.wasm.length; _++) {
|
292
252
|
const i = f.wasm[_];
|
293
253
|
if (!i || !i[0]) continue;
|
@@ -415,8 +375,6 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
415
375
|
const br = brs.at(-1);
|
416
376
|
const ret = rets.at(-1);
|
417
377
|
if (ret && ret !== Blocktype.void) {
|
418
|
-
// console.log(vals, ret);
|
419
|
-
// console.log(decompile(f.wasm.slice(_ - 5, _ + 1)));
|
420
378
|
if (vals.length > 0) line(`_r${br} = ${removeBrackets(vals.pop())}`);
|
421
379
|
// vals.push(`_r${br}`);
|
422
380
|
}
|
@@ -425,8 +383,6 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
425
383
|
line(`} else {`, false);
|
426
384
|
depth++;
|
427
385
|
|
428
|
-
// reset "stack"
|
429
|
-
// vals = [];
|
430
386
|
break;
|
431
387
|
}
|
432
388
|
|
@@ -441,8 +397,6 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
441
397
|
const br = brs.pop();
|
442
398
|
const ret = rets.pop();
|
443
399
|
if (ret && ret !== Blocktype.void) {
|
444
|
-
// console.log(vals, ret);
|
445
|
-
// console.log(decompile(f.wasm.slice(_ - 5, _ + 1)));
|
446
400
|
if (vals.length > 0) line(`_r${br} = ${removeBrackets(vals.pop())}`);
|
447
401
|
vals.push(`_r${br}`);
|
448
402
|
}
|
@@ -541,18 +495,14 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
541
495
|
|
542
496
|
case Opcodes.br: {
|
543
497
|
const ret = rets[brDepth - i[1] - 1];
|
544
|
-
// console.log(rets, brDepth, i[1], brDepth - i[1] - 1, ret, vals);
|
545
498
|
if (ret !== Blocktype.void) line(`_r${brs[brDepth - i[1] - 1]} = ${removeBrackets(vals.pop())}`);
|
546
499
|
line(`goto j${brs[brDepth - i[1] - 1]}`);
|
547
500
|
|
548
|
-
// // reset "stack"
|
549
|
-
// vals = [];
|
550
501
|
break;
|
551
502
|
}
|
552
503
|
|
553
504
|
case Opcodes.br_if: {
|
554
505
|
const ret = rets[brDepth - i[1] - 1];
|
555
|
-
// console.log(rets, brDepth, i[1], brDepth - i[1] - 1, ret, vals);
|
556
506
|
|
557
507
|
let cond = removeBrackets(vals.pop());
|
558
508
|
if (!lastCond) {
|
@@ -602,7 +552,6 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
602
552
|
}
|
603
553
|
|
604
554
|
log.warning('2c', `unimplemented op: ${invOpcodes[i[0]]}`);
|
605
|
-
// todo(`unimplemented op: ${invOpcodes[i[0]]}`);
|
606
555
|
}
|
607
556
|
|
608
557
|
lastCond = false;
|
@@ -1,8 +1,8 @@
|
|
1
|
-
import { Valtype, FuncType,
|
2
|
-
import { encodeVector, encodeString, encodeLocal, unsignedLEB128, signedLEB128 } from './encoding.js';
|
3
|
-
import { number } from './embedding.js';
|
1
|
+
import { Valtype, FuncType, ExportDesc, Section, Magic, ModuleVersion, Opcodes, PageSize, Reftype } from './wasmSpec.js';
|
2
|
+
import { encodeVector, encodeString, encodeLocal, unsignedLEB128, signedLEB128, unsignedLEB128_into, signedLEB128_into, ieee754_binary64_into } from './encoding.js';
|
4
3
|
import { importedFuncs } from './builtins.js';
|
5
|
-
import { log } from
|
4
|
+
import { log } from './log.js';
|
5
|
+
import Prefs from './prefs.js';
|
6
6
|
|
7
7
|
const createSection = (type, data) => [
|
8
8
|
type,
|
@@ -26,12 +26,12 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
26
26
|
|
27
27
|
const optLevel = parseInt(process.argv.find(x => x.startsWith('-O'))?.[2] ?? 1);
|
28
28
|
|
29
|
-
const compileHints =
|
30
|
-
if (compileHints) log.warning('
|
29
|
+
const compileHints = Prefs.compileHints;
|
30
|
+
if (compileHints) log.warning('assemble', 'compile hints is V8 only w/ experimental arg! (you used -compile-hints)');
|
31
31
|
|
32
32
|
const getType = (params, returns) => {
|
33
33
|
const hash = `${params.join(',')}_${returns.join(',')}`;
|
34
|
-
if (optLog) log('
|
34
|
+
if (Prefs.optLog) log('assemble', `getType(${JSON.stringify(params)}, ${JSON.stringify(returns)}) -> ${hash} | cache: ${typeCache[hash]}`);
|
35
35
|
if (optLevel >= 1 && typeCache[hash] !== undefined) return typeCache[hash];
|
36
36
|
|
37
37
|
const type = [ FuncType, ...encodeVector(params), ...encodeVector(returns) ];
|
@@ -44,7 +44,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
44
44
|
|
45
45
|
let importFuncs = [];
|
46
46
|
|
47
|
-
if (optLevel < 1) {
|
47
|
+
if (optLevel < 1 || !Prefs.treeshakeWasmImports) {
|
48
48
|
importFuncs = importedFuncs;
|
49
49
|
} else {
|
50
50
|
let imports = new Map();
|
@@ -79,11 +79,11 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
79
79
|
}
|
80
80
|
globalThis.importFuncs = importFuncs;
|
81
81
|
|
82
|
-
if (optLog) log('
|
82
|
+
if (Prefs.optLog) log('assemble', `treeshake: using ${importFuncs.length}/${importedFuncs.length} imports`);
|
83
83
|
|
84
84
|
const importSection = importFuncs.length === 0 ? [] : createSection(
|
85
85
|
Section.import,
|
86
|
-
encodeVector(importFuncs.map(x => [ 0, ...encodeString(x.import), ExportDesc.func, getType(new Array(x.params).fill(valtypeBinary), new Array(x.returns).fill(valtypeBinary)) ]))
|
86
|
+
encodeVector(importFuncs.map(x => [ 0, ...encodeString(x.import), ExportDesc.func, getType(new Array(x.params).fill(x.name.startsWith('profile') ? Valtype.i32 : valtypeBinary), new Array(x.returns).fill(valtypeBinary)) ]))
|
87
87
|
);
|
88
88
|
|
89
89
|
const funcSection = createSection(
|
@@ -91,22 +91,75 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
91
91
|
encodeVector(funcs.map(x => getType(x.params, x.returns))) // type indexes
|
92
92
|
);
|
93
93
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
'compilationHints',
|
98
|
-
// for now just do everything as optimise eager
|
99
|
-
encodeVector(funcs.map(_ => chHint(0x02, 0x02, 0x02)))
|
94
|
+
const tableSection = !funcs.table ? [] : createSection(
|
95
|
+
Section.table,
|
96
|
+
encodeVector([ [ Reftype.funcref, 0x00, funcs.length ] ])
|
100
97
|
);
|
101
98
|
|
102
|
-
const
|
103
|
-
Section.
|
104
|
-
encodeVector(
|
99
|
+
const elementSection = !funcs.table ? [] : createSection(
|
100
|
+
Section.element,
|
101
|
+
encodeVector([ [
|
102
|
+
0x00,
|
103
|
+
Opcodes.i32_const, 0, Opcodes.end,
|
104
|
+
encodeVector(funcs.map(x => x.index))
|
105
|
+
] ])
|
105
106
|
);
|
106
107
|
|
108
|
+
// const t0 = performance.now();
|
109
|
+
|
110
|
+
// specially optimized assembly for globals as this version is much (>5x) faster than traditional createSection()
|
111
|
+
const globalsValues = Object.values(globals);
|
112
|
+
|
113
|
+
let globalSection = [];
|
114
|
+
if (globalsValues.length > 0) {
|
115
|
+
let data = unsignedLEB128(globalsValues.length);
|
116
|
+
for (let i = 0; i < globalsValues.length; i++) {
|
117
|
+
const global = globalsValues[i];
|
118
|
+
|
119
|
+
switch (global.type) {
|
120
|
+
case Valtype.i32:
|
121
|
+
if (i > 0) data.push(Opcodes.end, Valtype.i32, 0x01, Opcodes.i32_const);
|
122
|
+
else data.push(Valtype.i32, 0x01, Opcodes.i32_const);
|
123
|
+
|
124
|
+
signedLEB128_into(global.init ?? 0, data);
|
125
|
+
break;
|
126
|
+
|
127
|
+
case Valtype.i64:
|
128
|
+
if (i > 0) data.push(Opcodes.end, Valtype.i64, 0x01, Opcodes.i64_const);
|
129
|
+
else data.push(Valtype.i64, 0x01, Opcodes.i64_const);
|
130
|
+
|
131
|
+
signedLEB128_into(global.init ?? 0, data);
|
132
|
+
break;
|
133
|
+
|
134
|
+
case Valtype.f64:
|
135
|
+
if (i > 0) data.push(Opcodes.end, Valtype.f64, 0x01, Opcodes.f64_const);
|
136
|
+
else data.push(Valtype.f64, 0x01, Opcodes.f64_const);
|
137
|
+
|
138
|
+
ieee754_binary64_into(global.init ?? 0, data);
|
139
|
+
break;
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
data.push(Opcodes.end);
|
144
|
+
|
145
|
+
globalSection.push(Section.global);
|
146
|
+
|
147
|
+
unsignedLEB128_into(data.length, globalSection);
|
148
|
+
globalSection = globalSection.concat(data);
|
149
|
+
}
|
150
|
+
|
151
|
+
// if (Prefs.profileCompiler) {
|
152
|
+
// const log = console.log;
|
153
|
+
// console.log = function () {
|
154
|
+
// log.apply(this, arguments);
|
155
|
+
// console.log = log;
|
156
|
+
// console.log(` a. assembled global section in ${(performance.now() - t0).toFixed(2)}ms\n`);
|
157
|
+
// };
|
158
|
+
// }
|
159
|
+
|
107
160
|
const exports = funcs.filter(x => x.export).map((x, i) => [ ...encodeString(x.name === 'main' ? 'm' : x.name), ExportDesc.func, x.index ]);
|
108
161
|
|
109
|
-
if (
|
162
|
+
if (Prefs.alwaysMemory && pages.size === 0) pages.set('--always-memory', 0);
|
110
163
|
if (optLevel === 0) pages.set('O0 precaution', 0);
|
111
164
|
|
112
165
|
const usesMemory = pages.size > 0;
|
@@ -169,7 +222,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
169
222
|
unsignedLEB128(data.length)
|
170
223
|
);
|
171
224
|
|
172
|
-
if (
|
225
|
+
if (Prefs.sections) console.log({
|
173
226
|
typeSection: typeSection.map(x => x.toString(16)),
|
174
227
|
importSection: importSection.map(x => x.toString(16)),
|
175
228
|
funcSection: funcSection.map(x => x.toString(16)),
|
@@ -179,6 +232,14 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
179
232
|
dataSection: dataSection.map(x => x.toString(16)),
|
180
233
|
});
|
181
234
|
|
235
|
+
// compilation hints section - unspecd, v8 only
|
236
|
+
// https://github.com/WebAssembly/design/issues/1473#issuecomment-1431274746
|
237
|
+
const chSection = !compileHints ? [] : customSection(
|
238
|
+
'compilationHints',
|
239
|
+
// for now just do everything as optimize eager
|
240
|
+
encodeVector(funcs.map(_ => chHint(0x02, 0x02, 0x02)))
|
241
|
+
);
|
242
|
+
|
182
243
|
return Uint8Array.from([
|
183
244
|
...Magic,
|
184
245
|
...ModuleVersion,
|
@@ -186,10 +247,12 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
186
247
|
...importSection,
|
187
248
|
...funcSection,
|
188
249
|
...chSection,
|
250
|
+
...tableSection,
|
189
251
|
...memorySection,
|
190
252
|
...tagSection,
|
191
253
|
...globalSection,
|
192
254
|
...exportSection,
|
255
|
+
...elementSection,
|
193
256
|
...dataCountSection,
|
194
257
|
...codeSection,
|
195
258
|
...dataSection
|
@@ -0,0 +1,72 @@
|
|
1
|
+
export default () => {
|
2
|
+
let out = `// @porf --funsafe-no-unlikely-proto-checks --valtype=i32
|
3
|
+
`;
|
4
|
+
|
5
|
+
const noArgs = (a0, a1) => out += `
|
6
|
+
export const __String_prototype_${a0} = (_this: string) => {
|
7
|
+
let out: string = Porffor.s\`<${a1}>\`;
|
8
|
+
|
9
|
+
let outPtr: i32 = Porffor.wasm\`local.get \${out}\` + ${(2 + a1.length) * 2};
|
10
|
+
|
11
|
+
let thisPtr: i32 = Porffor.wasm\`local.get \${_this}\`;
|
12
|
+
let thisLen: i32 = _this.length;
|
13
|
+
let endPtr: i32 = thisPtr + thisLen * 2;
|
14
|
+
|
15
|
+
while (thisPtr < endPtr) {
|
16
|
+
let chr: i32 = Porffor.wasm.i32.load16_u(thisPtr, 0, 4);
|
17
|
+
Porffor.wasm.i32.store16(outPtr, chr, 0, 4);
|
18
|
+
|
19
|
+
thisPtr += 2;
|
20
|
+
outPtr += 2;
|
21
|
+
}
|
22
|
+
|
23
|
+
Porffor.wasm.i32.store16(outPtr, 60, 0, 4); // <
|
24
|
+
Porffor.wasm.i32.store16(outPtr, 47, 0, 6); // /
|
25
|
+
|
26
|
+
${[...a1].map((x, i) => ` Porffor.wasm.i32.store16(outPtr, ${x.charCodeAt(0)}, 0, ${8 + i * 2}); // ${x}`).join('\n')}
|
27
|
+
|
28
|
+
Porffor.wasm.i32.store16(outPtr, 62, 0, ${8 + a1.length * 2}); // >
|
29
|
+
|
30
|
+
out.length = thisLen + ${a1.length * 2 + 2 + 3};
|
31
|
+
|
32
|
+
return out;
|
33
|
+
};
|
34
|
+
export const __ByteString_prototype_${a0} = (_this: bytestring) => {
|
35
|
+
let out: bytestring = Porffor.bs\`<${a1}>\`;
|
36
|
+
|
37
|
+
let outPtr: i32 = Porffor.wasm\`local.get \${out}\` + ${2 + a1.length};
|
38
|
+
|
39
|
+
let thisPtr: i32 = Porffor.wasm\`local.get \${_this}\`;
|
40
|
+
let thisLen: i32 = _this.length;
|
41
|
+
let endPtr: i32 = thisPtr + thisLen;
|
42
|
+
|
43
|
+
while (thisPtr < endPtr) {
|
44
|
+
let chr: i32 = Porffor.wasm.i32.load8_u(thisPtr++, 0, 4);
|
45
|
+
Porffor.wasm.i32.store8(outPtr++, chr, 0, 4);
|
46
|
+
}
|
47
|
+
|
48
|
+
Porffor.wasm.i32.store8(outPtr, 60, 0, 4); // <
|
49
|
+
Porffor.wasm.i32.store8(outPtr, 47, 0, 5); // /
|
50
|
+
|
51
|
+
${[...a1].map((x, i) => ` Porffor.wasm.i32.store8(outPtr, ${x.charCodeAt(0)}, 0, ${6 + i}); // ${x}`).join('\n')}
|
52
|
+
|
53
|
+
Porffor.wasm.i32.store8(outPtr, 62, 0, ${6 + a1.length}); // >
|
54
|
+
|
55
|
+
out.length = thisLen + ${a1.length * 2 + 2 + 3};
|
56
|
+
|
57
|
+
return out;
|
58
|
+
};
|
59
|
+
`;
|
60
|
+
|
61
|
+
noArgs('big', 'big');
|
62
|
+
noArgs('blink', 'blink');
|
63
|
+
noArgs('bold', 'b');
|
64
|
+
noArgs('fixed', 'tt');
|
65
|
+
noArgs('italics', 'i');
|
66
|
+
noArgs('small', 'small');
|
67
|
+
noArgs('strike', 'strike');
|
68
|
+
noArgs('sub', 'sub');
|
69
|
+
noArgs('sup', 'sup');
|
70
|
+
|
71
|
+
return out;
|
72
|
+
};
|
@@ -0,0 +1,18 @@
|
|
1
|
+
// @porf --valtype=i32
|
2
|
+
|
3
|
+
export const __String_prototype_trimLeft = (_this: string) => {
|
4
|
+
return __String_prototype_trimStart(_this);
|
5
|
+
};
|
6
|
+
|
7
|
+
export const __ByteString_prototype_trimLeft = (_this: string) => {
|
8
|
+
return __ByteString_prototype_trimStart(_this);
|
9
|
+
};
|
10
|
+
|
11
|
+
|
12
|
+
export const __String_prototype_trimRight = (_this: string) => {
|
13
|
+
return __String_prototype_trimEnd(_this);
|
14
|
+
};
|
15
|
+
|
16
|
+
export const __ByteString_prototype_trimRight = (_this: string) => {
|
17
|
+
return __ByteString_prototype_trimEnd(_this);
|
18
|
+
};
|