porffor 0.2.0-15592d6 → 0.2.0-181627c
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/builtins/base64.ts +48 -28
- package/compiler/builtins/porffor.d.ts +5 -0
- package/compiler/builtins.js +78 -1
- package/compiler/codeGen.js +28 -27
- package/compiler/index.js +8 -14
- package/compiler/opt.js +25 -24
- package/compiler/parse.js +4 -2
- package/compiler/precompile.js +19 -9
- package/compiler/prefs.js +22 -0
- package/compiler/prototype.js +8 -6
- package/compiler/sections.js +6 -5
- package/demo.js +2 -2
- package/hello +0 -0
- package/package.json +1 -1
- package/rhemyn/compile.js +2 -1
- package/tmp.c +20 -1116
package/compiler/precompile.js
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
import { Opcodes } from './wasmSpec.js';
|
2
|
+
|
1
3
|
import fs from 'node:fs';
|
2
4
|
import { join } from 'node:path';
|
3
5
|
|
@@ -20,11 +22,6 @@ const compile = async (file, [ _funcs, _globals ]) => {
|
|
20
22
|
}
|
21
23
|
process.argv = argv.concat(args);
|
22
24
|
|
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
25
|
// const porfParse = (await import(`./parse.js?_=${Date.now()}`)).default;
|
29
26
|
// const porfCodegen = (await import(`./codeGen.js?_=${Date.now()}`)).default;
|
30
27
|
|
@@ -34,17 +31,29 @@ const compile = async (file, [ _funcs, _globals ]) => {
|
|
34
31
|
|
35
32
|
let { funcs, globals, data, exceptions } = porfCompile(source, ['module']);
|
36
33
|
|
37
|
-
|
38
|
-
for (const x of
|
34
|
+
const exports = funcs.filter(x => x.export);
|
35
|
+
for (const x of exports) {
|
39
36
|
if (x.data) x.data = x.data.map(x => data[x]);
|
40
37
|
if (x.exceptions) x.exceptions = x.exceptions.map(x => {
|
41
38
|
const obj = exceptions[x];
|
42
39
|
if (obj) obj.exceptId = x;
|
43
40
|
return obj;
|
44
41
|
}).filter(x => x);
|
42
|
+
|
43
|
+
for (const y of x.wasm) {
|
44
|
+
if (y[0] === Opcodes.call) {
|
45
|
+
const f = funcs.find(x => x.index === y[1]);
|
46
|
+
if (!f) continue;
|
47
|
+
|
48
|
+
if (!f.internal) throw 'todo';
|
49
|
+
|
50
|
+
x.used ??= [];
|
51
|
+
x.used.push(f.name);
|
52
|
+
}
|
53
|
+
}
|
45
54
|
}
|
46
55
|
|
47
|
-
_funcs.push(...
|
56
|
+
_funcs.push(...exports);
|
48
57
|
_globals.push(...Object.values(globals));
|
49
58
|
};
|
50
59
|
|
@@ -59,7 +68,7 @@ const precompile = async () => {
|
|
59
68
|
|
60
69
|
// todo: globals, exceptions, pages per func
|
61
70
|
|
62
|
-
return `// autogenerated by precompile.js
|
71
|
+
return `// autogenerated by compiler/precompile.js
|
63
72
|
|
64
73
|
export const BuiltinFuncs = function() {
|
65
74
|
${funcs.map(x => ` this.${x.name} = {
|
@@ -72,6 +81,7 @@ ${funcs.map(x => ` this.${x.name} = {
|
|
72
81
|
${x.pages && x.pages.size > 0 ? ` pages: ${JSON.stringify(Object.fromEntries(x.pages.entries()))},` : ''}
|
73
82
|
${x.data && x.data.length > 0 ? ` data: ${JSON.stringify(x.data)},` : ''}
|
74
83
|
${x.exceptions && x.exceptions.length > 0 ? ` exceptions: ${JSON.stringify(x.exceptions)},` : ''}
|
84
|
+
${x.used && x.used.length > 0 ? ` used: ${JSON.stringify(x.used)},` : ''}
|
75
85
|
};`.replaceAll('\n\n', '\n')).join('\n')}
|
76
86
|
}`;
|
77
87
|
};
|
@@ -0,0 +1,22 @@
|
|
1
|
+
const cache = {};
|
2
|
+
const obj = new Proxy({}, {
|
3
|
+
get(_, p) {
|
4
|
+
// intentionally misses with undefined values cached
|
5
|
+
if (cache[p]) return cache[p];
|
6
|
+
|
7
|
+
return cache[p] = (() => {
|
8
|
+
// fooBar -> foo-bar
|
9
|
+
const name = p[0] === '_' ? p : p.replace(/[A-Z]/g, c => `-${c.toLowerCase()}`);
|
10
|
+
if (process.argv.includes('-' + name)) return true;
|
11
|
+
|
12
|
+
const valArg = process.argv.find(x => x.startsWith(`-${name}=`));
|
13
|
+
if (valArg) return valArg.slice(name.length + 2);
|
14
|
+
|
15
|
+
return undefined;
|
16
|
+
})();
|
17
|
+
}
|
18
|
+
});
|
19
|
+
|
20
|
+
obj.uncache = () => cache = {};
|
21
|
+
|
22
|
+
export default obj;
|
package/compiler/prototype.js
CHANGED
@@ -2,6 +2,7 @@ import { Opcodes, Blocktype, Valtype, ValtypeSize, PageSize } from "./wasmSpec.j
|
|
2
2
|
import { number } from "./embedding.js";
|
3
3
|
import { unsignedLEB128 } from "./encoding.js";
|
4
4
|
import { UNDEFINED } from "./builtins.js";
|
5
|
+
import Prefs from './prefs.js';
|
5
6
|
|
6
7
|
// todo: do not duplicate this
|
7
8
|
const TYPES = {
|
@@ -23,9 +24,10 @@ const TYPES = {
|
|
23
24
|
// todo: turn these into built-ins once arrays and these become less hacky
|
24
25
|
|
25
26
|
export const PrototypeFuncs = function() {
|
26
|
-
const noUnlikelyChecks =
|
27
|
-
|
28
|
-
|
27
|
+
const noUnlikelyChecks = Prefs.funsafeNoUnlikelyProtoChecks;
|
28
|
+
|
29
|
+
let zeroChecks;
|
30
|
+
if (Prefs.zeroChecks) zeroChecks = Prefs.zeroChecks.split('=')[1].split(',').reduce((acc, x) => { acc[x.toLowerCase()] = true; return acc; }, {});
|
29
31
|
else zeroChecks = {};
|
30
32
|
|
31
33
|
this[TYPES._array] = {
|
@@ -489,10 +491,10 @@ export const PrototypeFuncs = function() {
|
|
489
491
|
this[TYPES.string].isWellFormed.local2 = Valtype.i32;
|
490
492
|
this[TYPES.string].isWellFormed.returnType = TYPES.boolean;
|
491
493
|
|
492
|
-
if (
|
494
|
+
if (Prefs.bytestring) {
|
493
495
|
this[TYPES._bytestring] = {
|
494
496
|
at: (pointer, length, wIndex, iTmp, _, arrayShell) => {
|
495
|
-
const [ newOut, newPointer ] = arrayShell(1, '
|
497
|
+
const [ newOut, newPointer ] = arrayShell(1, 'i8');
|
496
498
|
|
497
499
|
return [
|
498
500
|
// setup new/out array
|
@@ -548,7 +550,7 @@ export const PrototypeFuncs = function() {
|
|
548
550
|
|
549
551
|
// todo: out of bounds properly
|
550
552
|
charAt: (pointer, length, wIndex, _1, _2, arrayShell) => {
|
551
|
-
const [ newOut, newPointer ] = arrayShell(1, '
|
553
|
+
const [ newOut, newPointer ] = arrayShell(1, 'i8');
|
552
554
|
|
553
555
|
return [
|
554
556
|
// setup new/out array
|
package/compiler/sections.js
CHANGED
@@ -3,6 +3,7 @@ import { encodeVector, encodeString, encodeLocal, unsignedLEB128, signedLEB128 }
|
|
3
3
|
import { number } from './embedding.js';
|
4
4
|
import { importedFuncs } from './builtins.js';
|
5
5
|
import { log } from "./log.js";
|
6
|
+
import Prefs from './prefs.js';
|
6
7
|
|
7
8
|
const createSection = (type, data) => [
|
8
9
|
type,
|
@@ -26,12 +27,12 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
26
27
|
|
27
28
|
const optLevel = parseInt(process.argv.find(x => x.startsWith('-O'))?.[2] ?? 1);
|
28
29
|
|
29
|
-
const compileHints =
|
30
|
+
const compileHints = Prefs.compileHints;
|
30
31
|
if (compileHints) log.warning('sections', 'compile hints is V8 only w/ experimental arg! (you used -compile-hints)');
|
31
32
|
|
32
33
|
const getType = (params, returns) => {
|
33
34
|
const hash = `${params.join(',')}_${returns.join(',')}`;
|
34
|
-
if (optLog) log('sections', `getType(${JSON.stringify(params)}, ${JSON.stringify(returns)}) -> ${hash} | cache: ${typeCache[hash]}`);
|
35
|
+
if (Prefs.optLog) log('sections', `getType(${JSON.stringify(params)}, ${JSON.stringify(returns)}) -> ${hash} | cache: ${typeCache[hash]}`);
|
35
36
|
if (optLevel >= 1 && typeCache[hash] !== undefined) return typeCache[hash];
|
36
37
|
|
37
38
|
const type = [ FuncType, ...encodeVector(params), ...encodeVector(returns) ];
|
@@ -79,7 +80,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
79
80
|
}
|
80
81
|
globalThis.importFuncs = importFuncs;
|
81
82
|
|
82
|
-
if (optLog) log('sections', `treeshake: using ${importFuncs.length}/${importedFuncs.length} imports`);
|
83
|
+
if (Prefs.optLog) log('sections', `treeshake: using ${importFuncs.length}/${importedFuncs.length} imports`);
|
83
84
|
|
84
85
|
const importSection = importFuncs.length === 0 ? [] : createSection(
|
85
86
|
Section.import,
|
@@ -106,7 +107,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
106
107
|
|
107
108
|
const exports = funcs.filter(x => x.export).map((x, i) => [ ...encodeString(x.name === 'main' ? 'm' : x.name), ExportDesc.func, x.index ]);
|
108
109
|
|
109
|
-
if (
|
110
|
+
if (Prefs.alwaysMemory && pages.size === 0) pages.set('-always-memory', 0);
|
110
111
|
if (optLevel === 0) pages.set('O0 precaution', 0);
|
111
112
|
|
112
113
|
const usesMemory = pages.size > 0;
|
@@ -169,7 +170,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
169
170
|
unsignedLEB128(data.length)
|
170
171
|
);
|
171
172
|
|
172
|
-
if (
|
173
|
+
if (Prefs.sections) console.log({
|
173
174
|
typeSection: typeSection.map(x => x.toString(16)),
|
174
175
|
importSection: importSection.map(x => x.toString(16)),
|
175
176
|
funcSection: funcSection.map(x => x.toString(16)),
|
package/demo.js
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
foo();
|
1
|
+
// foo();
|
2
2
|
|
3
|
-
|
3
|
+
console.log('Hello, World!');
|
package/hello
ADDED
Binary file
|
package/package.json
CHANGED
package/rhemyn/compile.js
CHANGED
@@ -2,6 +2,7 @@ import { Blocktype, Opcodes, Valtype, PageSize, ValtypeSize } from '../compiler/
|
|
2
2
|
import { number } from '../compiler/embedding.js';
|
3
3
|
import { signedLEB128, unsignedLEB128 } from '../compiler/encoding.js';
|
4
4
|
import parse from './parse.js';
|
5
|
+
import Prefs from '../compiler/prefs.js';
|
5
6
|
|
6
7
|
// local indexes
|
7
8
|
const BasePointer = 0; // base string pointer
|
@@ -80,7 +81,7 @@ const generate = (node, negated = false, get = true, func = 'test') => {
|
|
80
81
|
})[func], Valtype.i32)
|
81
82
|
];
|
82
83
|
|
83
|
-
if (
|
84
|
+
if (Prefs.regexLog) {
|
84
85
|
const underline = x => `\u001b[4m\u001b[1m${x}\u001b[0m`;
|
85
86
|
console.log(`\n${underline('ast')}`);
|
86
87
|
console.log(node);
|