porffor 0.50.19 → 0.50.21
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/README.md +0 -3
- package/compiler/assemble.js +119 -63
- package/compiler/builtins/array.ts +0 -1
- package/compiler/builtins.js +0 -6
- package/compiler/builtins_precompiled.js +443 -443
- package/compiler/codegen.js +53 -22
- package/compiler/embedding.js +1 -14
- package/compiler/encoding.js +16 -0
- package/compiler/index.js +38 -29
- package/compiler/wrap.js +0 -3
- package/package.json +1 -1
- package/runner/index.js +1 -1
- package/ts.js +198655 -0
package/compiler/codegen.js
CHANGED
@@ -305,7 +305,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
305
305
|
|
306
306
|
case 'DebuggerStatement':
|
307
307
|
return cacheAst(decl, [
|
308
|
-
[ Opcodes.call, importedFuncs.debugger ],
|
308
|
+
// [ Opcodes.call, importedFuncs.debugger ],
|
309
309
|
number(UNDEFINED)
|
310
310
|
]);
|
311
311
|
|
@@ -332,7 +332,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
332
332
|
return cacheAst(decl, generateTemplate(scope, decl));
|
333
333
|
|
334
334
|
case 'TaggedTemplateExpression':
|
335
|
-
return cacheAst(decl, generateTaggedTemplate(scope, decl, global, name));
|
335
|
+
return cacheAst(decl, generateTaggedTemplate(scope, decl, global, name, valueUnused));
|
336
336
|
|
337
337
|
case 'ExportNamedDeclaration':
|
338
338
|
if (!decl.declaration) return todo(scope, 'unsupported export declaration', true);
|
@@ -2438,26 +2438,26 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2438
2438
|
// pointer, align, offset
|
2439
2439
|
i32_load: { imms: 2, args: [ true ], returns: 1 },
|
2440
2440
|
// pointer, value, align, offset
|
2441
|
-
i32_store: { imms: 2, args: [ true, true ], returns: 0 },
|
2441
|
+
i32_store: { imms: 2, args: [ true, true ], returns: 0, addValue: true },
|
2442
2442
|
// pointer, align, offset
|
2443
2443
|
i32_load8_u: { imms: 2, args: [ true ], returns: 1 },
|
2444
2444
|
// pointer, value, align, offset
|
2445
|
-
i32_store8: { imms: 2, args: [ true, true ], returns: 0 },
|
2445
|
+
i32_store8: { imms: 2, args: [ true, true ], returns: 0, addValue: true },
|
2446
2446
|
// pointer, align, offset
|
2447
2447
|
i32_load16_u: { imms: 2, args: [ true ], returns: 1 },
|
2448
2448
|
// pointer, value, align, offset
|
2449
|
-
i32_store16: { imms: 2, args: [ true, true ], returns: 0 },
|
2449
|
+
i32_store16: { imms: 2, args: [ true, true ], returns: 0, addValue: true },
|
2450
2450
|
|
2451
2451
|
// pointer, align, offset
|
2452
2452
|
f64_load: { imms: 2, args: [ true ], returns: 0 }, // 0 due to not i32
|
2453
2453
|
// pointer, value, align, offset
|
2454
|
-
f64_store: { imms: 2, args: [ true, false ], returns: 0 },
|
2454
|
+
f64_store: { imms: 2, args: [ true, false ], returns: 0, addValue: true },
|
2455
2455
|
|
2456
2456
|
// value
|
2457
2457
|
i32_const: { imms: 1, args: [], returns: 0 },
|
2458
2458
|
|
2459
2459
|
// dst, src, size, _, _
|
2460
|
-
memory_copy: { imms: 2, args: [ true, true, true ], returns: 0 }
|
2460
|
+
memory_copy: { imms: 2, args: [ true, true, true ], returns: 0, addValue: true }
|
2461
2461
|
};
|
2462
2462
|
|
2463
2463
|
const opName = name.slice('__Porffor_wasm_'.length);
|
@@ -2486,7 +2486,8 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2486
2486
|
return [
|
2487
2487
|
...argOut,
|
2488
2488
|
[ ...opcode, ...imms ],
|
2489
|
-
...(new Array(op.returns).fill(Opcodes.i32_from))
|
2489
|
+
...(new Array(op.returns).fill(Opcodes.i32_from)),
|
2490
|
+
...(op.addValue ? [ number(UNDEFINED) ] : [])
|
2490
2491
|
];
|
2491
2492
|
}
|
2492
2493
|
} else {
|
@@ -2689,6 +2690,11 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2689
2690
|
out.push(Opcodes.i32_trunc_sat_f64_s);
|
2690
2691
|
}
|
2691
2692
|
|
2693
|
+
if ((builtinFuncs[name] && builtinFuncs[name].returns?.length === 0) ||
|
2694
|
+
(importedFuncs[name] != null && importedFuncs[importedFuncs[name]]?.returns === 0)) {
|
2695
|
+
out.push(number(UNDEFINED));
|
2696
|
+
}
|
2697
|
+
|
2692
2698
|
return out;
|
2693
2699
|
};
|
2694
2700
|
|
@@ -3049,15 +3055,18 @@ const typeIsNotOneOf = (type, types, valtype = Valtype.i32) => {
|
|
3049
3055
|
return out;
|
3050
3056
|
};
|
3051
3057
|
|
3052
|
-
const allocVar = (scope, name, global = false, type = true) => {
|
3058
|
+
const allocVar = (scope, name, global = false, type = true, redecl = false) => {
|
3053
3059
|
const target = global ? globals : scope.locals;
|
3054
3060
|
|
3055
3061
|
// already declared
|
3056
3062
|
if (Object.hasOwn(target, name)) {
|
3057
|
-
|
3058
|
-
|
3059
|
-
|
3060
|
-
|
3063
|
+
if (redecl) {
|
3064
|
+
// force change old local name(s)
|
3065
|
+
target['#redecl_' + name + uniqId()] = target[name];
|
3066
|
+
if (type) target['#redecl_' + name + '#type' + uniqId()] = target[name + '#type'];
|
3067
|
+
} else {
|
3068
|
+
return target[name].idx;
|
3069
|
+
}
|
3061
3070
|
}
|
3062
3071
|
|
3063
3072
|
let idx = global ? globals['#ind']++ : scope.localInd++;
|
@@ -4300,7 +4309,10 @@ const inferLoopEnd = scope => {
|
|
4300
4309
|
const generateIf = (scope, decl) => {
|
4301
4310
|
if (globalThis.precompile && decl.test?.tag?.name === '__Porffor_comptime_flag') {
|
4302
4311
|
const flag = decl.test.quasi.quasis[0].value.raw;
|
4303
|
-
return [
|
4312
|
+
return [
|
4313
|
+
[ null, 'comptime_flag', flag, decl.consequent, '#', Prefs ],
|
4314
|
+
number(UNDEFINED)
|
4315
|
+
];
|
4304
4316
|
}
|
4305
4317
|
|
4306
4318
|
const out = truthy(scope, generate(scope, decl.test), getNodeType(scope, decl.test), false, true);
|
@@ -5148,7 +5160,19 @@ const generateLabel = (scope, decl) => {
|
|
5148
5160
|
const name = decl.label.name;
|
5149
5161
|
scope.labels.set(name, depth.length);
|
5150
5162
|
|
5151
|
-
|
5163
|
+
const out = generate(scope, decl.body);
|
5164
|
+
|
5165
|
+
// if block statement, wrap in block to allow for breaking
|
5166
|
+
if (decl.body.type === 'BlockStatement') {
|
5167
|
+
out.unshift([ Opcodes.block, Blocktype.void ]);
|
5168
|
+
out.push(
|
5169
|
+
[ Opcodes.drop ],
|
5170
|
+
[ Opcodes.end ],
|
5171
|
+
number(UNDEFINED)
|
5172
|
+
);
|
5173
|
+
}
|
5174
|
+
|
5175
|
+
return out;
|
5152
5176
|
};
|
5153
5177
|
|
5154
5178
|
const ensureTag = (exceptionMode = Prefs.exceptionMode ?? 'stack') => {
|
@@ -6260,7 +6284,7 @@ export const generateTemplate = (scope, decl) => {
|
|
6260
6284
|
return generate(scope, current);
|
6261
6285
|
};
|
6262
6286
|
|
6263
|
-
const generateTaggedTemplate = (scope, decl, global = false, name = undefined) => {
|
6287
|
+
const generateTaggedTemplate = (scope, decl, global = false, name = undefined, valueUnused = false) => {
|
6264
6288
|
const intrinsics = {
|
6265
6289
|
__Porffor_wasm: str => {
|
6266
6290
|
let out = [];
|
@@ -6307,6 +6331,11 @@ const generateTaggedTemplate = (scope, decl, global = false, name = undefined) =
|
|
6307
6331
|
out.push([ ...inst, ...immediates.flatMap(x => encodeFunc(x)) ]);
|
6308
6332
|
}
|
6309
6333
|
|
6334
|
+
// add value to stack if value unused as 99% typically means
|
6335
|
+
// no value on stack at end of wasm
|
6336
|
+
// unless final op is return
|
6337
|
+
if (valueUnused && out.at(-1)[0] !== Opcodes.return) out.push(number(UNDEFINED));
|
6338
|
+
|
6310
6339
|
return out;
|
6311
6340
|
},
|
6312
6341
|
|
@@ -6428,8 +6457,6 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6428
6457
|
return [ func, out ];
|
6429
6458
|
}
|
6430
6459
|
|
6431
|
-
globalThis.progress?.(null, ' ' + name);
|
6432
|
-
|
6433
6460
|
const params = decl.params ?? [];
|
6434
6461
|
|
6435
6462
|
// TODO: share scope/locals between !!!
|
@@ -6489,7 +6516,7 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6489
6516
|
const { name, def, destr, type } = args[i];
|
6490
6517
|
|
6491
6518
|
func.localInd = i * 2;
|
6492
|
-
allocVar(func, name, false);
|
6519
|
+
allocVar(func, name, false, true, true);
|
6493
6520
|
|
6494
6521
|
func.localInd = localInd;
|
6495
6522
|
if (type) {
|
@@ -6733,15 +6760,18 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6733
6760
|
return [ func, out ];
|
6734
6761
|
};
|
6735
6762
|
|
6763
|
+
let largestBlockBody = 0;
|
6736
6764
|
const generateBlock = (scope, decl) => {
|
6737
6765
|
let out = [];
|
6738
6766
|
|
6739
6767
|
scope.inferTree ??= [];
|
6740
6768
|
scope.inferTree.push(decl);
|
6741
6769
|
|
6742
|
-
let j = 0;
|
6743
|
-
|
6770
|
+
let len = decl.body.length, j = 0;
|
6771
|
+
if (len > largestBlockBody) largestBlockBody = len;
|
6772
|
+
for (let i = 0; i < len; i++) {
|
6744
6773
|
const x = decl.body[i];
|
6774
|
+
if (len >= largestBlockBody) globalThis.progress?.(`${i}/${len}`);
|
6745
6775
|
if (isEmptyNode(x)) continue;
|
6746
6776
|
|
6747
6777
|
if (j++ > 0) out.push([ Opcodes.drop ]);
|
@@ -6917,6 +6947,7 @@ export default program => {
|
|
6917
6947
|
data = [];
|
6918
6948
|
currentFuncIndex = importedFuncs.length;
|
6919
6949
|
typeswitchDepth = 0;
|
6950
|
+
largestBlockBody = 0;
|
6920
6951
|
usedTypes = new Set([ TYPES.empty, TYPES.undefined, TYPES.number, TYPES.boolean, TYPES.function ]);
|
6921
6952
|
coctc = new Map();
|
6922
6953
|
globalInfer = new Map();
|
@@ -7034,4 +7065,4 @@ export default program => {
|
|
7034
7065
|
delete globals['#ind'];
|
7035
7066
|
|
7036
7067
|
return { funcs, globals, tags, exceptions, pages, data };
|
7037
|
-
};
|
7068
|
+
};
|
package/compiler/embedding.js
CHANGED
@@ -8,17 +8,4 @@ export const number = (n, valtype = valtypeBinary) => {
|
|
8
8
|
signedLEB128_into(n, out);
|
9
9
|
|
10
10
|
return out;
|
11
|
-
};
|
12
|
-
|
13
|
-
export const enforceOneByte = arr => [ arr[0] ?? 0 ];
|
14
|
-
export const enforceTwoBytes = arr => [ arr[0] ?? 0, arr[1] ?? 0 ];
|
15
|
-
export const enforceFourBytes = arr => [ arr[0] ?? 0, arr[1] ?? 0, arr[2] ?? 0, arr[3] ?? 0 ];
|
16
|
-
export const enforceEightBytes = arr => [ arr[0] ?? 0, arr[1] ?? 0, arr[2] ?? 0, arr[3] ?? 0, arr[4] ?? 0, arr[5] ?? 0, arr[6] ?? 0, arr[7] ?? 0 ];
|
17
|
-
|
18
|
-
export const i32x4 = (a, b, c, d) => [ [
|
19
|
-
...Opcodes.v128_const,
|
20
|
-
...enforceFourBytes(signedLEB128(a)),
|
21
|
-
...enforceFourBytes(signedLEB128(b)),
|
22
|
-
...enforceFourBytes(signedLEB128(c)),
|
23
|
-
...enforceFourBytes(signedLEB128(d))
|
24
|
-
] ];
|
11
|
+
};
|
package/compiler/encoding.js
CHANGED
@@ -64,6 +64,22 @@ export const unsignedLEB128 = n => {
|
|
64
64
|
return buffer;
|
65
65
|
};
|
66
66
|
|
67
|
+
export const unsignedLEB128_length = n => {
|
68
|
+
if (n < 0) n = n >>> 0;
|
69
|
+
if (n <= 127) return 1;
|
70
|
+
if (n <= 16383) return 2;
|
71
|
+
if (n <= 2097151) return 3;
|
72
|
+
if (n <= 268435455) return 4;
|
73
|
+
if (n <= 34359738367) return 5;
|
74
|
+
|
75
|
+
let length = 0;
|
76
|
+
do {
|
77
|
+
length++;
|
78
|
+
n >>>= 7;
|
79
|
+
} while (n > 0);
|
80
|
+
return length;
|
81
|
+
};
|
82
|
+
|
67
83
|
export const big_signedLEB128 = n => {
|
68
84
|
// just input for small numbers (for perf as common)
|
69
85
|
if (n >= 0n && n <= 63n) return [ Number(n) ];
|
package/compiler/index.js
CHANGED
@@ -35,7 +35,7 @@ const progressStart = msg => {
|
|
35
35
|
|
36
36
|
const log = (extra, after) => {
|
37
37
|
const pre = extra ? `${extra}` : spinner[spin++ % 4];
|
38
|
-
process.stdout.write(`\r\u001b[90m${' '.repeat(
|
38
|
+
process.stdout.write(`\r\u001b[90m${' '.repeat(120)}\r${' '.repeat(12 - pre.length)}${pre} ${msg}${after ?? ''}\u001b[0m`);
|
39
39
|
};
|
40
40
|
log();
|
41
41
|
|
@@ -48,7 +48,7 @@ const progressDone = (msg, start) => {
|
|
48
48
|
clearInterval(progressInterval);
|
49
49
|
|
50
50
|
const timeStr = (performance.now() - start).toFixed(0);
|
51
|
-
console.log(`\r${' '.repeat(
|
51
|
+
console.log(`\r${' '.repeat(120)}\r\u001b[90m${' '.repeat(10 - timeStr.length)}${timeStr}ms\u001b[0m \u001b[92m${msg}\u001b[0m`);
|
52
52
|
progressLines++;
|
53
53
|
};
|
54
54
|
const progressClear = () => {
|
@@ -66,9 +66,8 @@ export default (code, module = undefined) => {
|
|
66
66
|
let target = Prefs.target ?? 'wasm';
|
67
67
|
if (Prefs.native) target = 'native';
|
68
68
|
|
69
|
-
const
|
70
|
-
|
71
|
-
let outFile = Prefs.o;
|
69
|
+
const outFile = Prefs.o;
|
70
|
+
const logProgress = Prefs.profileCompiler || (Prefs.target && outFile && !Prefs.native && globalThis.file);
|
72
71
|
|
73
72
|
globalThis.valtype = Prefs.valtype ?? 'f64';
|
74
73
|
globalThis.valtypeBinary = Valtype[valtype];
|
@@ -214,6 +213,12 @@ export default (code, module = undefined) => {
|
|
214
213
|
if (target === 'wasm' && outFile) {
|
215
214
|
fs.writeFileSync(outFile, Buffer.from(wasm));
|
216
215
|
|
216
|
+
if (logProgress) {
|
217
|
+
const total = performance.now();
|
218
|
+
progressClear();
|
219
|
+
console.log(`\u001b[90m[${total.toFixed(0)}ms]\u001b[0m \u001b[32mcompiled ${globalThis.file} \u001b[90m->\u001b[0m \u001b[92m${outFile}\u001b[90m (${(fs.statSync(outFile).size / 1000).toFixed(1)}KB)\u001b[0m`);
|
220
|
+
}
|
221
|
+
|
217
222
|
if (process.version) process.exit();
|
218
223
|
}
|
219
224
|
|
@@ -227,6 +232,12 @@ export default (code, module = undefined) => {
|
|
227
232
|
console.log(c);
|
228
233
|
}
|
229
234
|
|
235
|
+
if (logProgress) {
|
236
|
+
const total = performance.now();
|
237
|
+
progressClear();
|
238
|
+
console.log(`\u001b[90m[${total.toFixed(0)}ms]\u001b[0m \u001b[32mcompiled ${globalThis.file} \u001b[90m->\u001b[0m \u001b[92m${outFile}\u001b[90m (${(fs.statSync(outFile).size / 1000).toFixed(1)}KB)\u001b[0m`);
|
239
|
+
}
|
240
|
+
|
230
241
|
if (process.version) process.exit();
|
231
242
|
}
|
232
243
|
|
@@ -260,35 +271,33 @@ export default (code, module = undefined) => {
|
|
260
271
|
|
261
272
|
if (logProgress) progressStart(`compiled C to native (using ${compiler})`, t5);
|
262
273
|
|
263
|
-
if (
|
264
|
-
|
265
|
-
const cleanup = () => {
|
266
|
-
try {
|
267
|
-
fs.unlinkSync(outFile);
|
268
|
-
} catch {}
|
269
|
-
};
|
270
|
-
|
271
|
-
process.on('exit', cleanup);
|
272
|
-
process.on('beforeExit', cleanup);
|
273
|
-
process.on('SIGINT', () => {
|
274
|
-
cleanup();
|
275
|
-
process.exit();
|
276
|
-
});
|
277
|
-
|
278
|
-
const runArgs = process.argv.slice(2).filter(x => !x.startsWith('-'));
|
274
|
+
if (Prefs.native) {
|
275
|
+
const cleanup = () => {
|
279
276
|
try {
|
280
|
-
|
277
|
+
fs.unlinkSync(outFile);
|
281
278
|
} catch {}
|
282
|
-
}
|
279
|
+
};
|
283
280
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
281
|
+
process.on('exit', cleanup);
|
282
|
+
process.on('beforeExit', cleanup);
|
283
|
+
process.on('SIGINT', () => {
|
284
|
+
cleanup();
|
285
|
+
process.exit();
|
286
|
+
});
|
287
|
+
|
288
|
+
const runArgs = process.argv.slice(2).filter(x => !x.startsWith('-'));
|
289
|
+
try {
|
290
|
+
execSync([ outFile, ...runArgs.slice(1) ].join(' '), { stdio: 'inherit' });
|
291
|
+
} catch {}
|
292
|
+
}
|
289
293
|
|
290
|
-
|
294
|
+
if (logProgress) {
|
295
|
+
const total = performance.now();
|
296
|
+
progressClear();
|
297
|
+
console.log(`\u001b[90m[${total.toFixed(0)}ms]\u001b[0m \u001b[32mcompiled ${globalThis.file} \u001b[90m->\u001b[0m \u001b[92m${outFile}\u001b[90m (${(fs.statSync(outFile).size / 1000).toFixed(1)}KB)\u001b[0m`);
|
291
298
|
}
|
299
|
+
|
300
|
+
process.exit();
|
292
301
|
}
|
293
302
|
|
294
303
|
return out;
|
package/compiler/wrap.js
CHANGED
package/package.json
CHANGED