porffor 0.2.0-dcc06c8 → 0.2.0-e04e26f
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 +20 -20
- package/README.md +63 -44
- package/asur/README.md +2 -0
- package/asur/index.js +1262 -0
- package/byg/index.js +237 -0
- package/compiler/2c.js +1 -1
- package/compiler/{sections.js → assemble.js} +58 -11
- package/compiler/builtins/annexb_string.js +72 -0
- package/compiler/builtins/annexb_string.ts +19 -0
- package/compiler/builtins/array.ts +145 -0
- package/compiler/builtins/base64.ts +103 -40
- package/compiler/builtins/crypto.ts +120 -0
- package/compiler/builtins/date.ts +1128 -0
- package/compiler/builtins/escape.ts +141 -0
- package/compiler/builtins/int.ts +147 -0
- package/compiler/builtins/number.ts +527 -0
- package/compiler/builtins/porffor.d.ts +33 -1
- package/compiler/builtins/string.ts +1055 -0
- package/compiler/builtins/tostring.ts +45 -0
- package/compiler/builtins.js +452 -238
- package/compiler/{codeGen.js → codegen.js} +799 -290
- package/compiler/embedding.js +22 -22
- package/compiler/encoding.js +108 -10
- package/compiler/generated_builtins.js +1133 -0
- package/compiler/index.js +16 -14
- package/compiler/log.js +6 -3
- package/compiler/opt.js +23 -22
- package/compiler/parse.js +31 -25
- package/compiler/precompile.js +66 -22
- package/compiler/prefs.js +5 -1
- package/compiler/prototype.js +4 -20
- package/compiler/types.js +37 -0
- package/compiler/wasmSpec.js +28 -8
- package/compiler/wrap.js +51 -47
- package/package.json +9 -5
- package/porf +2 -0
- package/rhemyn/compile.js +3 -2
- package/rhemyn/parse.js +323 -320
- package/rhemyn/test/parse.js +58 -58
- package/runner/compare.js +34 -34
- package/runner/debug.js +122 -0
- package/runner/index.js +31 -9
- package/runner/profiler.js +102 -0
- package/runner/repl.js +40 -7
- package/runner/sizes.js +37 -37
- package/demo.js +0 -3
- package/demo.ts +0 -1
- package/filesize.cmd +0 -2
- package/hello +0 -0
- 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 -152
- package/util/enum.js +0 -20
package/compiler/index.js
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
import { underline, bold, log } from './log.js';
|
2
2
|
import parse from './parse.js';
|
3
|
-
import
|
3
|
+
import codegen from './codegen.js';
|
4
4
|
import opt from './opt.js';
|
5
|
-
import
|
5
|
+
import assemble from './assemble.js';
|
6
6
|
import decompile from './decompile.js';
|
7
7
|
import toc from './2c.js';
|
8
8
|
import Prefs from './prefs.js';
|
@@ -26,29 +26,29 @@ const logFuncs = (funcs, globals, exceptions) => {
|
|
26
26
|
console.log();
|
27
27
|
};
|
28
28
|
|
29
|
-
const
|
29
|
+
const fs = (typeof process?.version !== 'undefined' ? (await import('node:fs')) : undefined);
|
30
30
|
const execSync = (typeof process?.version !== 'undefined' ? (await import('node:child_process')).execSync : undefined);
|
31
31
|
|
32
32
|
export default (code, flags) => {
|
33
33
|
const t0 = performance.now();
|
34
34
|
const program = parse(code, flags);
|
35
|
-
if (
|
35
|
+
if (Prefs.profileCompiler) console.log(`1. parsed in ${(performance.now() - t0).toFixed(2)}ms`);
|
36
36
|
|
37
37
|
const t1 = performance.now();
|
38
|
-
const { funcs, globals, tags, exceptions, pages, data } =
|
39
|
-
if (
|
38
|
+
const { funcs, globals, tags, exceptions, pages, data } = codegen(program);
|
39
|
+
if (Prefs.profileCompiler) console.log(`2. generated code in ${(performance.now() - t1).toFixed(2)}ms`);
|
40
40
|
|
41
41
|
if (Prefs.funcs) logFuncs(funcs, globals, exceptions);
|
42
42
|
|
43
43
|
const t2 = performance.now();
|
44
44
|
opt(funcs, globals, pages, tags, exceptions);
|
45
|
-
if (
|
45
|
+
if (Prefs.profileCompiler) console.log(`3. optimized in ${(performance.now() - t2).toFixed(2)}ms`);
|
46
46
|
|
47
47
|
if (Prefs.optFuncs) logFuncs(funcs, globals, exceptions);
|
48
48
|
|
49
49
|
const t3 = performance.now();
|
50
|
-
const
|
51
|
-
if (
|
50
|
+
const wasm = assemble(funcs, globals, tags, pages, data, flags);
|
51
|
+
if (Prefs.profileCompiler) console.log(`4. assembled in ${(performance.now() - t3).toFixed(2)}ms`);
|
52
52
|
|
53
53
|
if (Prefs.allocLog) {
|
54
54
|
const wasmPages = Math.ceil((pages.size * pageSize) / 65536);
|
@@ -57,13 +57,13 @@ export default (code, flags) => {
|
|
57
57
|
console.log([...pages.keys()].map(x => `\x1B[36m - ${x}\x1B[0m`).join('\n') + '\n');
|
58
58
|
}
|
59
59
|
|
60
|
-
const out = { wasm
|
60
|
+
const out = { wasm, funcs, globals, tags, exceptions, pages, data };
|
61
61
|
|
62
62
|
const target = Prefs.target ?? 'wasm';
|
63
63
|
const outFile = Prefs.o;
|
64
64
|
|
65
65
|
if (target === 'wasm' && outFile) {
|
66
|
-
writeFileSync(outFile, Buffer.from(
|
66
|
+
fs.writeFileSync(outFile, Buffer.from(wasm));
|
67
67
|
|
68
68
|
if (process.version) process.exit();
|
69
69
|
}
|
@@ -73,7 +73,7 @@ export default (code, flags) => {
|
|
73
73
|
out.c = c;
|
74
74
|
|
75
75
|
if (outFile) {
|
76
|
-
writeFileSync(outFile, c);
|
76
|
+
fs.writeFileSync(outFile, c);
|
77
77
|
} else {
|
78
78
|
console.log(c);
|
79
79
|
}
|
@@ -88,17 +88,19 @@ export default (code, flags) => {
|
|
88
88
|
if (compiler === 'zig') compiler = [ 'zig', 'cc' ];
|
89
89
|
else compiler = [ compiler ];
|
90
90
|
|
91
|
-
const tmpfile = '
|
91
|
+
const tmpfile = 'porffor_tmp.c';
|
92
92
|
// const args = [ compiler, tmpfile, '-o', outFile ?? (process.platform === 'win32' ? 'out.exe' : 'out'), '-' + cO, '-march=native', '-s', '-fno-unwind-tables', '-fno-asynchronous-unwind-tables', '-ffunction-sections', '-fdata-sections', '-Wl', '-fno-ident', '-fno-exceptions', '-ffast-math' ];
|
93
93
|
// const args = [ ...compiler, tmpfile, '-o', outFile ?? (process.platform === 'win32' ? 'out.exe' : 'out'), '-' + cO, '-march=native', '-s', '-ffast-math', '-fno-exceptions', '-target', 'x86_64-linux' ];
|
94
94
|
const args = [ ...compiler, tmpfile, '-o', outFile ?? (process.platform === 'win32' ? 'out.exe' : 'out'), '-' + cO, '-march=native', '-s', '-ffast-math', '-fno-exceptions' ];
|
95
95
|
|
96
96
|
const c = toc(out);
|
97
|
-
writeFileSync(tmpfile, c);
|
97
|
+
fs.writeFileSync(tmpfile, c);
|
98
98
|
|
99
99
|
// obvious command escape is obvious
|
100
100
|
execSync(args.join(' '), { stdio: 'inherit' });
|
101
101
|
|
102
|
+
fs.unlinkSync(tmpfile);
|
103
|
+
|
102
104
|
if (process.version) process.exit();
|
103
105
|
}
|
104
106
|
|
package/compiler/log.js
CHANGED
@@ -5,11 +5,14 @@ export const bold = x => `\u001b[1m${x}\u001b[0m`;
|
|
5
5
|
const areaColors = {
|
6
6
|
codegen: [ 20, 80, 250 ],
|
7
7
|
opt: [ 250, 20, 80 ],
|
8
|
-
|
8
|
+
assemble: [ 20, 250, 80 ],
|
9
9
|
alloc: [ 250, 250, 20 ],
|
10
|
-
|
11
|
-
'2c': [ 20, 250, 250 ]
|
10
|
+
parse: [ 240, 240, 240 ],
|
11
|
+
'2c': [ 20, 250, 250 ],
|
12
|
+
wrap: [ 250, 100, 20 ]
|
12
13
|
};
|
13
14
|
|
15
|
+
// for (const x in areaColors) console.log(rgb(areaColors[x][0], areaColors[x][1], areaColors[x][2], x));
|
16
|
+
|
14
17
|
export const log = (area, ...args) => console.log(`\u001b[90m[\u001b[0m${rgb(...areaColors[area], area)}\u001b[90m]\u001b[0m`, ...args);
|
15
18
|
log.warning = (area, ...args) => log(area, '\u001b[93m' + args[0], ...args.slice(1), '\u001b[0m');
|
package/compiler/opt.js
CHANGED
@@ -100,8 +100,9 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
100
100
|
|
101
101
|
if (Prefs.optInlineOnly) return;
|
102
102
|
|
103
|
-
|
104
|
-
const
|
103
|
+
// todo: this breaks exceptions after due to indexes not being adjusted
|
104
|
+
// const tagUse = tags.reduce((acc, x) => { acc[x.idx] = 0; return acc; }, {});
|
105
|
+
// const exceptionUse = exceptions.reduce((acc, _, i) => { acc[i] = 0; return acc; }, {});
|
105
106
|
|
106
107
|
// wasm transform pass
|
107
108
|
for (const f of funcs) {
|
@@ -109,7 +110,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
109
110
|
|
110
111
|
const lastType = f.locals['#last_type'];
|
111
112
|
|
112
|
-
let runs = 2; // how many by default?
|
113
|
+
let runs = (+Prefs.optWasmRuns) || 2; // todo: how many by default?
|
113
114
|
while (runs > 0) {
|
114
115
|
runs--;
|
115
116
|
|
@@ -131,12 +132,12 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
131
132
|
if (inst[0] === Opcodes.local_get) getCount[inst[1]]++;
|
132
133
|
if (inst[0] === Opcodes.local_set || inst[0] === Opcodes.local_tee) setCount[inst[1]]++;
|
133
134
|
|
134
|
-
if (inst[0] === Opcodes.throw) {
|
135
|
-
|
135
|
+
// if (inst[0] === Opcodes.throw) {
|
136
|
+
// tagUse[inst[1]]++;
|
136
137
|
|
137
|
-
|
138
|
-
|
139
|
-
}
|
138
|
+
// const exceptId = read_signedLEB128(wasm[i - 1].slice(1));
|
139
|
+
// exceptionUse[exceptId]++;
|
140
|
+
// }
|
140
141
|
|
141
142
|
if (inst[0] === Opcodes.block) {
|
142
143
|
// remove unneeded blocks (no brs inside)
|
@@ -171,14 +172,14 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
171
172
|
}
|
172
173
|
}
|
173
174
|
|
174
|
-
if (inst[inst.length - 1] === 'string_only' && !pages.
|
175
|
+
if (inst[inst.length - 1] === 'string_only' && !pages.hasAnyString) {
|
175
176
|
// remove this inst
|
176
177
|
wasm.splice(i, 1);
|
177
178
|
if (i > 0) i--;
|
178
179
|
inst = wasm[i];
|
179
180
|
}
|
180
181
|
|
181
|
-
if (inst[inst.length - 1] === 'string_only|start' && !pages.
|
182
|
+
if (inst[inst.length - 1] === 'string_only|start' && !pages.hasAnyString) {
|
182
183
|
let j = i;
|
183
184
|
for (; j < wasm.length; j++) {
|
184
185
|
const op = wasm[j];
|
@@ -553,18 +554,18 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
553
554
|
}
|
554
555
|
}
|
555
556
|
|
556
|
-
for (const x in tagUse) {
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
}
|
562
|
-
|
563
|
-
for (const x of Object.keys(exceptionUse).sort((a, b) => b - a)) {
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
}
|
557
|
+
// for (const x in tagUse) {
|
558
|
+
// if (tagUse[x] === 0) {
|
559
|
+
// const el = tags.find(y => y.idx === x);
|
560
|
+
// tags.splice(tags.indexOf(el), 1);
|
561
|
+
// }
|
562
|
+
// }
|
563
|
+
|
564
|
+
// for (const x of Object.keys(exceptionUse).sort((a, b) => b - a)) {
|
565
|
+
// if (exceptionUse[x] === 0) {
|
566
|
+
// exceptions.splice(+x, 1);
|
567
|
+
// }
|
568
|
+
// }
|
568
569
|
|
569
570
|
// return funcs;
|
570
571
|
};
|
package/compiler/parse.js
CHANGED
@@ -20,37 +20,43 @@ globalThis.typedInput = types && Prefs.optTypes;
|
|
20
20
|
// - hermes-parser
|
21
21
|
// - @babel/parser
|
22
22
|
|
23
|
-
|
23
|
+
globalThis.parser = '';
|
24
|
+
let parse;
|
24
25
|
const loadParser = async (fallbackParser = 'acorn', forceParser) => {
|
25
26
|
parser = forceParser ?? process.argv.find(x => x.startsWith('-parser='))?.split('=')?.[1] ?? fallbackParser;
|
26
|
-
0, { parse } = (await import((globalThis.document ? 'https://esm.sh/' : '') + parser));
|
27
|
+
0, { parse } = (await import((globalThis.document || globalThis.Deno ? 'https://esm.sh/' : '') + parser));
|
27
28
|
};
|
28
29
|
globalThis._porf_loadParser = loadParser;
|
29
30
|
await loadParser(types ? '@babel/parser' : undefined);
|
30
31
|
|
31
|
-
if (types && !['@babel/parser', 'hermes-parser'].includes(parser)) log.warning('
|
32
|
+
if (types && !['@babel/parser', 'hermes-parser'].includes(parser)) log.warning('parse', `passed -parse-types with a parser (${parser}) which does not support`);
|
32
33
|
|
33
34
|
export default (input, flags) => {
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
35
|
+
try {
|
36
|
+
const ast = parse(input, {
|
37
|
+
// acorn
|
38
|
+
ecmaVersion: 'latest',
|
39
|
+
|
40
|
+
// meriyah
|
41
|
+
next: true,
|
42
|
+
module: flags.includes('module'),
|
43
|
+
webcompat: true,
|
44
|
+
|
45
|
+
// babel
|
46
|
+
plugins: types ? ['estree', 'typescript'] : ['estree'],
|
47
|
+
|
48
|
+
// multiple
|
49
|
+
sourceType: flags.includes('module') ? 'module' : 'script',
|
50
|
+
ranges: false,
|
51
|
+
tokens: false,
|
52
|
+
comments: false,
|
53
|
+
});
|
54
|
+
|
55
|
+
if (ast.type === 'File') return ast.program;
|
56
|
+
|
57
|
+
return ast;
|
58
|
+
} catch (e) {
|
59
|
+
// normalize error class thrown by 3rd party parsers
|
60
|
+
throw new SyntaxError(e.message, { cause: e });
|
61
|
+
}
|
56
62
|
};
|
package/compiler/precompile.js
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
import { Opcodes } from './wasmSpec.js';
|
2
|
+
import { TYPES } from './types.js';
|
3
|
+
|
1
4
|
import fs from 'node:fs';
|
2
5
|
import { join } from 'node:path';
|
3
6
|
|
@@ -10,21 +13,20 @@ const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
10
13
|
const argv = process.argv.slice();
|
11
14
|
|
12
15
|
const compile = async (file, [ _funcs, _globals ]) => {
|
13
|
-
|
14
|
-
|
16
|
+
let source = fs.readFileSync(file, 'utf8');
|
17
|
+
let first = source.slice(0, source.indexOf('\n'));
|
18
|
+
|
19
|
+
if (first.startsWith('export default')) {
|
20
|
+
source = (await import(file)).default();
|
21
|
+
first = source.slice(0, source.indexOf('\n'));
|
22
|
+
}
|
15
23
|
|
16
|
-
let args = ['-bytestring'];
|
17
|
-
if (file.endsWith('.ts')) args.push('-parse-types', '-opt-types');
|
24
|
+
let args = ['-bytestring', '-todo-time=compile', '-no-aot-pointer-opt', '-no-treeshake-wasm-imports', '-scoped-page-names', '-parse-types', '-opt-types'];
|
18
25
|
if (first.startsWith('// @porf')) {
|
19
26
|
args = args.concat(first.slice('// @porf '.length).split(' '));
|
20
27
|
}
|
21
28
|
process.argv = argv.concat(args);
|
22
29
|
|
23
|
-
// globalThis.optLog = process.argv.includes('-opt-log');
|
24
|
-
// globalThis.codeLog = process.argv.includes('-code-log');
|
25
|
-
// globalThis.allocLog = process.argv.includes('-alloc-log');
|
26
|
-
// globalThis.regexLog = process.argv.includes('-regex-log');
|
27
|
-
|
28
30
|
// const porfParse = (await import(`./parse.js?_=${Date.now()}`)).default;
|
29
31
|
// const porfCodegen = (await import(`./codeGen.js?_=${Date.now()}`)).default;
|
30
32
|
|
@@ -34,17 +36,54 @@ const compile = async (file, [ _funcs, _globals ]) => {
|
|
34
36
|
|
35
37
|
let { funcs, globals, data, exceptions } = porfCompile(source, ['module']);
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
39
|
+
const allocated = new Set();
|
40
|
+
|
41
|
+
const exports = funcs.filter(x => x.export && x.name !== 'main');
|
42
|
+
for (const x of exports) {
|
43
|
+
if (x.data) {
|
44
|
+
x.data = x.data.map(x => data[x]);
|
45
|
+
for (const y in x.data) {
|
46
|
+
x.data[y].offset -= x.data[0].offset;
|
47
|
+
}
|
48
|
+
}
|
40
49
|
if (x.exceptions) x.exceptions = x.exceptions.map(x => {
|
41
50
|
const obj = exceptions[x];
|
42
51
|
if (obj) obj.exceptId = x;
|
43
52
|
return obj;
|
44
53
|
}).filter(x => x);
|
54
|
+
|
55
|
+
const locals = Object.keys(x.locals).reduce((acc, y) => {
|
56
|
+
acc[x.locals[y].idx] = { ...x.locals[y], name: y };
|
57
|
+
return acc;
|
58
|
+
}, {});
|
59
|
+
|
60
|
+
for (let i = 0; i < x.wasm.length; i++) {
|
61
|
+
const y = x.wasm[i];
|
62
|
+
const n = x.wasm[i + 1];
|
63
|
+
if (y[0] === Opcodes.call) {
|
64
|
+
const f = funcs.find(x => x.index === y[1]);
|
65
|
+
if (!f) continue;
|
66
|
+
|
67
|
+
y[1] = f.name;
|
68
|
+
}
|
69
|
+
|
70
|
+
if (y[0] === Opcodes.const && (n[0] === Opcodes.local_set || n[0] === Opcodes.local_tee)) {
|
71
|
+
const l = locals[n[1]];
|
72
|
+
if (!l) continue;
|
73
|
+
if (![TYPES.string, TYPES._array, TYPES._bytestring].includes(l.metadata?.type)) continue;
|
74
|
+
if (!x.pages) continue;
|
75
|
+
|
76
|
+
const pageName = [...x.pages.keys()].find(z => z.endsWith(l.name));
|
77
|
+
if (!pageName || allocated.has(pageName)) continue;
|
78
|
+
allocated.add(pageName);
|
79
|
+
|
80
|
+
y.splice(0, 10, 'alloc', pageName, x.pages.get(pageName).type, valtypeBinary);
|
81
|
+
// y.push(x.pages.get(pageName));
|
82
|
+
}
|
83
|
+
}
|
45
84
|
}
|
46
85
|
|
47
|
-
_funcs.push(...
|
86
|
+
_funcs.push(...exports);
|
48
87
|
_globals.push(...Object.values(globals));
|
49
88
|
};
|
50
89
|
|
@@ -57,23 +96,28 @@ const precompile = async () => {
|
|
57
96
|
await compile(join(dir, file), [ funcs, globals ]);
|
58
97
|
}
|
59
98
|
|
60
|
-
//
|
99
|
+
// ${x.pages && x.pages.size > 0 ? ` pages: ${JSON.stringify(Object.fromEntries(x.pages.entries()))},` : ''}
|
100
|
+
// ${x.used && x.used.length > 0 ? ` used: ${JSON.stringify(x.used)},` : ''}
|
61
101
|
|
62
|
-
return `// autogenerated by precompile.js
|
102
|
+
return `// autogenerated by compiler/precompile.js
|
103
|
+
import { number } from './embedding.js';
|
63
104
|
|
64
105
|
export const BuiltinFuncs = function() {
|
65
106
|
${funcs.map(x => ` this.${x.name} = {
|
66
|
-
wasm: ${JSON.stringify(x.wasm)},
|
107
|
+
wasm: (scope, { allocPage, builtin }) => ${JSON.stringify(x.wasm.filter(x => x.length && x[0] != null)).replace(/\["alloc","(.*?)","(.*?)",(.*?)\]/g, (_, reason, type, valtype) => `...number(allocPage(scope, '${reason}', '${type}') * pageSize, ${valtype})`).replace(/\[16,"(.*?)"]/g, (_, name) => `[16, builtin('${name}')]`)},
|
67
108
|
params: ${JSON.stringify(x.params)},
|
68
109
|
typedParams: true,
|
69
110
|
returns: ${JSON.stringify(x.returns)},
|
70
|
-
typedReturns: true,
|
71
|
-
locals: ${JSON.stringify(Object.values(x.locals).slice(x.params.length
|
72
|
-
|
111
|
+
${x.returnType != null ? `returnType: ${JSON.stringify(x.returnType)}` : 'typedReturns: true'},
|
112
|
+
locals: ${JSON.stringify(Object.values(x.locals).slice(x.params.length).map(x => x.type))},
|
113
|
+
localNames: ${JSON.stringify(Object.keys(x.locals))},
|
73
114
|
${x.data && x.data.length > 0 ? ` data: ${JSON.stringify(x.data)},` : ''}
|
74
115
|
${x.exceptions && x.exceptions.length > 0 ? ` exceptions: ${JSON.stringify(x.exceptions)},` : ''}
|
75
|
-
};`.replaceAll('\n\n', '\n')).join('\n')}
|
76
|
-
}
|
116
|
+
};`.replaceAll('\n\n', '\n').replaceAll('\n\n', '\n')).join('\n')}
|
117
|
+
};`;
|
77
118
|
};
|
78
119
|
|
79
|
-
|
120
|
+
const code = await precompile();
|
121
|
+
// console.log(code);
|
122
|
+
|
123
|
+
fs.writeFileSync(join(__dirname, 'generated_builtins.js'), code);
|
package/compiler/prefs.js
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
const
|
1
|
+
const onByDefault = [ 'bytestring', 'aotPointerOpt' ];
|
2
|
+
|
3
|
+
let cache = {};
|
2
4
|
const obj = new Proxy({}, {
|
3
5
|
get(_, p) {
|
4
6
|
// intentionally misses with undefined values cached
|
@@ -8,10 +10,12 @@ const obj = new Proxy({}, {
|
|
8
10
|
// fooBar -> foo-bar
|
9
11
|
const name = p[0] === '_' ? p : p.replace(/[A-Z]/g, c => `-${c.toLowerCase()}`);
|
10
12
|
if (process.argv.includes('-' + name)) return true;
|
13
|
+
if (process.argv.includes('-no-' + name)) return false;
|
11
14
|
|
12
15
|
const valArg = process.argv.find(x => x.startsWith(`-${name}=`));
|
13
16
|
if (valArg) return valArg.slice(name.length + 2);
|
14
17
|
|
18
|
+
if (onByDefault.includes(p)) return true;
|
15
19
|
return undefined;
|
16
20
|
})();
|
17
21
|
}
|
package/compiler/prototype.js
CHANGED
@@ -3,23 +3,7 @@ import { number } from "./embedding.js";
|
|
3
3
|
import { unsignedLEB128 } from "./encoding.js";
|
4
4
|
import { UNDEFINED } from "./builtins.js";
|
5
5
|
import Prefs from './prefs.js';
|
6
|
-
|
7
|
-
// todo: do not duplicate this
|
8
|
-
const TYPES = {
|
9
|
-
number: 0x00,
|
10
|
-
boolean: 0x01,
|
11
|
-
string: 0x02,
|
12
|
-
undefined: 0x03,
|
13
|
-
object: 0x04,
|
14
|
-
function: 0x05,
|
15
|
-
symbol: 0x06,
|
16
|
-
bigint: 0x07,
|
17
|
-
|
18
|
-
// these are not "typeof" types but tracked internally
|
19
|
-
_array: 0x10,
|
20
|
-
_regexp: 0x11,
|
21
|
-
_bytestring: 0x12
|
22
|
-
};
|
6
|
+
import { TYPES } from './types.js';
|
23
7
|
|
24
8
|
// todo: turn these into built-ins once arrays and these become less hacky
|
25
9
|
|
@@ -150,7 +134,7 @@ export const PrototypeFuncs = function() {
|
|
150
134
|
shift: (pointer, length) => [
|
151
135
|
// if length == 0, noop
|
152
136
|
...length.getCachedI32(),
|
153
|
-
Opcodes.i32_eqz,
|
137
|
+
[ Opcodes.i32_eqz ],
|
154
138
|
[ Opcodes.if, Blocktype.void ],
|
155
139
|
...number(UNDEFINED),
|
156
140
|
[ Opcodes.br, 1 ],
|
@@ -385,7 +369,7 @@ export const PrototypeFuncs = function() {
|
|
385
369
|
|
386
370
|
...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
|
387
371
|
[ Opcodes.if, Blocktype.void ],
|
388
|
-
...number(NaN),
|
372
|
+
...number(valtype === 'i32' ? -1 : NaN),
|
389
373
|
[ Opcodes.br, 1 ],
|
390
374
|
[ Opcodes.end ],
|
391
375
|
|
@@ -598,7 +582,7 @@ export const PrototypeFuncs = function() {
|
|
598
582
|
|
599
583
|
...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
|
600
584
|
[ Opcodes.if, Blocktype.void ],
|
601
|
-
...number(NaN),
|
585
|
+
...number(valtype === 'i32' ? -1 : NaN),
|
602
586
|
[ Opcodes.br, 1 ],
|
603
587
|
[ Opcodes.end ],
|
604
588
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
export const TYPES = {
|
2
|
+
number: 0x00,
|
3
|
+
boolean: 0x01,
|
4
|
+
string: 0x02,
|
5
|
+
undefined: 0x03,
|
6
|
+
object: 0x04,
|
7
|
+
function: 0x05,
|
8
|
+
symbol: 0x06,
|
9
|
+
bigint: 0x07
|
10
|
+
};
|
11
|
+
|
12
|
+
export const TYPE_NAMES = {
|
13
|
+
[TYPES.number]: 'Number',
|
14
|
+
[TYPES.boolean]: 'Boolean',
|
15
|
+
[TYPES.string]: 'String',
|
16
|
+
[TYPES.undefined]: 'undefined',
|
17
|
+
[TYPES.object]: 'Object',
|
18
|
+
[TYPES.function]: 'Function',
|
19
|
+
[TYPES.symbol]: 'Symbol',
|
20
|
+
[TYPES.bigint]: 'BigInt'
|
21
|
+
};
|
22
|
+
|
23
|
+
export const INTERNAL_TYPE_BASE = 0x10;
|
24
|
+
let internalTypeIndex = INTERNAL_TYPE_BASE;
|
25
|
+
const registerInternalType = name => {
|
26
|
+
const n = internalTypeIndex++;
|
27
|
+
TYPES['_' + name.toLowerCase()] = n;
|
28
|
+
TYPE_NAMES[n] = name;
|
29
|
+
};
|
30
|
+
|
31
|
+
// note: when adding a new internal type, please also add a deserializer to wrap.js
|
32
|
+
// (it is okay to add a throw todo deserializer for wips)
|
33
|
+
|
34
|
+
registerInternalType('Array');
|
35
|
+
registerInternalType('RegExp');
|
36
|
+
registerInternalType('ByteString');
|
37
|
+
registerInternalType('Date');
|
package/compiler/wasmSpec.js
CHANGED
@@ -1,4 +1,13 @@
|
|
1
|
-
|
1
|
+
const enumify = (...args) => {
|
2
|
+
const obj = {};
|
3
|
+
|
4
|
+
for (let i = 0; i < args.length; i++) {
|
5
|
+
obj[i] = args[i];
|
6
|
+
obj[args[i]] = i;
|
7
|
+
}
|
8
|
+
|
9
|
+
return obj;
|
10
|
+
};
|
2
11
|
|
3
12
|
export const Section = enumify('custom', 'type', 'import', 'func', 'table', 'memory', 'global', 'export', 'start', 'element', 'code', 'data', 'data_count', 'tag');
|
4
13
|
export const ExportDesc = enumify('func', 'table', 'mem', 'global', 'tag');
|
@@ -32,17 +41,16 @@ export const Opcodes = {
|
|
32
41
|
throw: 0x08,
|
33
42
|
rethrow: 0x09,
|
34
43
|
|
35
|
-
call: 0x10,
|
36
|
-
call_indirect: 0x11,
|
37
|
-
return_call: 0x12,
|
38
|
-
return_call_indirect: 0x13,
|
39
|
-
|
40
44
|
end: 0x0b,
|
41
45
|
br: 0x0c,
|
42
46
|
br_if: 0x0d,
|
43
47
|
br_table: 0x0e,
|
44
48
|
return: 0x0f,
|
49
|
+
|
45
50
|
call: 0x10,
|
51
|
+
call_indirect: 0x11,
|
52
|
+
return_call: 0x12,
|
53
|
+
return_call_indirect: 0x13,
|
46
54
|
|
47
55
|
drop: 0x1a,
|
48
56
|
|
@@ -62,13 +70,22 @@ export const Opcodes = {
|
|
62
70
|
i32_load16_s: 0x2e,
|
63
71
|
i32_load16_u: 0x2f,
|
64
72
|
|
65
|
-
|
66
|
-
|
73
|
+
i64_load8_s: 0x30,
|
74
|
+
i64_load8_u: 0x31,
|
75
|
+
i64_load16_s: 0x32,
|
76
|
+
i64_load16_u: 0x33,
|
67
77
|
|
68
78
|
i32_store: 0x36,
|
69
79
|
i64_store: 0x37,
|
70
80
|
f64_store: 0x39,
|
71
81
|
|
82
|
+
i32_store8: 0x3a,
|
83
|
+
i32_store16: 0x3b,
|
84
|
+
|
85
|
+
i64_store8: 0x3c,
|
86
|
+
i64_store16: 0x3d,
|
87
|
+
|
88
|
+
memory_size: 0x3f,
|
72
89
|
memory_grow: 0x40,
|
73
90
|
|
74
91
|
i32_const: 0x41,
|
@@ -100,6 +117,8 @@ export const Opcodes = {
|
|
100
117
|
i32_shl: 0x74,
|
101
118
|
i32_shr_s: 0x75,
|
102
119
|
i32_shr_u: 0x76,
|
120
|
+
i32_rotl: 0x77,
|
121
|
+
i32_rotr: 0x78,
|
103
122
|
|
104
123
|
i64_eqz: 0x50,
|
105
124
|
i64_eq: 0x51,
|
@@ -123,6 +142,7 @@ export const Opcodes = {
|
|
123
142
|
i64_shr_s: 0x87,
|
124
143
|
i64_shr_u: 0x88,
|
125
144
|
i64_rotl: 0x89,
|
145
|
+
i64_rotr: 0x8a,
|
126
146
|
|
127
147
|
f64_eq: 0x61,
|
128
148
|
f64_ne: 0x62,
|