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.
@@ -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
- // parser should catch this but sanity check anyway
3058
- // if (decl.kind !== 'var') return internalThrow(scope, 'SyntaxError', `Identifier '${unhackName(name)}' has already been declared`);
3059
-
3060
- return target[name].idx;
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 [ [ null, 'comptime_flag', flag, decl.consequent, '#', Prefs ] ];
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
- return generate(scope, decl.body);
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
- for (let i = 0; i < decl.body.length; i++) {
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
+ };
@@ -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
+ };
@@ -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(10 - pre.length)}${pre} ${msg}${after ?? ''}\u001b[0m`);
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(50)}\r\u001b[90m${' '.repeat(8 - timeStr.length)}${timeStr}ms\u001b[0m \u001b[92m${msg}\u001b[0m`);
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 logProgress = Prefs.profileCompiler || (target === 'native' && !Prefs.native && globalThis.file);
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 (process.version) {
264
- if (Prefs.native) {
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
- execSync([ outFile, ...runArgs.slice(1) ].join(' '), { stdio: 'inherit' });
277
+ fs.unlinkSync(outFile);
281
278
  } catch {}
282
- }
279
+ };
283
280
 
284
- if (logProgress) {
285
- const total = performance.now();
286
- progressClear();
287
- 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`);
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
- process.exit();
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
@@ -469,9 +469,6 @@ export default (source, module = undefined, customImports = {}, print = str => p
469
469
  return -1;
470
470
  }
471
471
  },
472
- b: () => {
473
- debugger;
474
- },
475
472
  ...customImports
476
473
  }
477
474
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "porffor",
3
3
  "description": "a basic experimental wip aot optimizing js -> wasm engine/compiler/runtime in js",
4
- "version": "0.50.19",
4
+ "version": "0.50.21",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "scripts": {},
package/runner/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from 'node:fs';
3
- globalThis.version = '0.50.19';
3
+ globalThis.version = '0.50.21';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {