porffor 0.2.0-5e33105 → 0.2.0-6aff0fa

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.
@@ -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 = {
@@ -16,15 +17,17 @@ const TYPES = {
16
17
 
17
18
  // these are not "typeof" types but tracked internally
18
19
  _array: 0x10,
19
- _regexp: 0x11
20
+ _regexp: 0x11,
21
+ _bytestring: 0x12
20
22
  };
21
23
 
22
24
  // todo: turn these into built-ins once arrays and these become less hacky
23
25
 
24
26
  export const PrototypeFuncs = function() {
25
- const noUnlikelyChecks = process.argv.includes('-funsafe-no-unlikely-proto-checks');
26
- let zeroChecks = process.argv.find(x => x.startsWith('-funsafe-zero-proto-checks='));
27
- if (zeroChecks) zeroChecks = zeroChecks.split('=')[1].split(',').reduce((acc, x) => { acc[x.toLowerCase()] = true; return acc; }, {});
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; }, {});
28
31
  else zeroChecks = {};
29
32
 
30
33
  this[TYPES._array] = {
@@ -71,7 +74,7 @@ export const PrototypeFuncs = function() {
71
74
  ],
72
75
 
73
76
  // todo: only for 1 argument
74
- push: (pointer, length, wNewMember) => [
77
+ push: (pointer, length, wNewMember, _1, _2, _3, unusedValue) => [
75
78
  // get memory offset of array at last index (length)
76
79
  ...length.getCachedI32(),
77
80
  ...number(ValtypeSize[valtype], Valtype.i32),
@@ -92,22 +95,28 @@ export const PrototypeFuncs = function() {
92
95
  ...number(1, Valtype.i32),
93
96
  [ Opcodes.i32_add ],
94
97
 
95
- ...length.setCachedI32(),
96
- ...length.getCachedI32(),
98
+ ...(unusedValue() ? [] : [
99
+ ...length.setCachedI32(),
100
+ ...length.getCachedI32(),
101
+ ])
97
102
  ]),
98
103
 
99
- ...length.getCachedI32(),
100
- Opcodes.i32_from_u
104
+ ...(unusedValue() ? [] : [
105
+ ...length.getCachedI32(),
106
+ Opcodes.i32_from_u
107
+ ])
101
108
 
102
109
  // ...length.get()
103
110
  ],
104
111
 
105
- pop: (pointer, length) => [
112
+ pop: (pointer, length, _1, _2, _3, _4, unusedValue) => [
106
113
  // if length == 0, noop
107
114
  ...length.getCachedI32(),
108
115
  [ Opcodes.i32_eqz ],
109
116
  [ Opcodes.if, Blocktype.void ],
110
- ...number(UNDEFINED),
117
+ ...(unusedValue() ? [] : [
118
+ ...number(UNDEFINED),
119
+ ]),
111
120
  [ Opcodes.br, 1 ],
112
121
  [ Opcodes.end ],
113
122
 
@@ -119,19 +128,23 @@ export const PrototypeFuncs = function() {
119
128
  ...number(1, Valtype.i32),
120
129
  [ Opcodes.i32_sub ],
121
130
 
122
- ...length.setCachedI32(),
123
- ...length.getCachedI32(),
131
+ ...(unusedValue() ? [] : [
132
+ ...length.setCachedI32(),
133
+ ...length.getCachedI32(),
134
+ ])
124
135
  ]),
125
136
 
126
137
  // load last element
127
- ...length.getCachedI32(),
128
- ...number(ValtypeSize[valtype], Valtype.i32),
129
- [ Opcodes.i32_mul ],
138
+ ...(unusedValue() ? [] : [
139
+ ...length.getCachedI32(),
140
+ ...number(ValtypeSize[valtype], Valtype.i32),
141
+ [ Opcodes.i32_mul ],
130
142
 
131
- ...pointer,
132
- [ Opcodes.i32_add ],
143
+ ...pointer,
144
+ [ Opcodes.i32_add ],
133
145
 
134
- [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(ValtypeSize.i32) ]
146
+ [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(ValtypeSize.i32) ]
147
+ ])
135
148
  ],
136
149
 
137
150
  shift: (pointer, length) => [
@@ -331,8 +344,8 @@ export const PrototypeFuncs = function() {
331
344
  ...number(0, Valtype.i32), // base 0 for store later
332
345
 
333
346
  ...wIndex,
334
-
335
347
  Opcodes.i32_to,
348
+
336
349
  ...number(ValtypeSize.i16, Valtype.i32),
337
350
  [ Opcodes.i32_mul ],
338
351
 
@@ -372,7 +385,7 @@ export const PrototypeFuncs = function() {
372
385
 
373
386
  ...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
374
387
  [ Opcodes.if, Blocktype.void ],
375
- ...number(NaN),
388
+ ...number(valtype === 'i32' ? -1 : NaN),
376
389
  [ Opcodes.br, 1 ],
377
390
  [ Opcodes.end ],
378
391
 
@@ -472,8 +485,151 @@ export const PrototypeFuncs = function() {
472
485
  this[TYPES.string].at.returnType = TYPES.string;
473
486
  this[TYPES.string].charAt.returnType = TYPES.string;
474
487
  this[TYPES.string].charCodeAt.local = Valtype.i32;
488
+ this[TYPES.string].charCodeAt.noPointerCache = zeroChecks.charcodeat;
475
489
 
476
490
  this[TYPES.string].isWellFormed.local = Valtype.i32;
477
491
  this[TYPES.string].isWellFormed.local2 = Valtype.i32;
478
492
  this[TYPES.string].isWellFormed.returnType = TYPES.boolean;
493
+
494
+ if (Prefs.bytestring) {
495
+ this[TYPES._bytestring] = {
496
+ at: (pointer, length, wIndex, iTmp, _, arrayShell) => {
497
+ const [ newOut, newPointer ] = arrayShell(1, 'i8');
498
+
499
+ return [
500
+ // setup new/out array
501
+ ...newOut,
502
+ [ Opcodes.drop ],
503
+
504
+ ...number(0, Valtype.i32), // base 0 for store later
505
+
506
+ ...wIndex,
507
+ Opcodes.i32_to_u,
508
+ [ Opcodes.local_tee, iTmp ],
509
+
510
+ // if index < 0: access index + array length
511
+ ...number(0, Valtype.i32),
512
+ [ Opcodes.i32_lt_s ],
513
+ [ Opcodes.if, Blocktype.void ],
514
+ [ Opcodes.local_get, iTmp ],
515
+ ...length.getCachedI32(),
516
+ [ Opcodes.i32_add ],
517
+ [ Opcodes.local_set, iTmp ],
518
+ [ Opcodes.end ],
519
+
520
+ // if still < 0 or >= length: return undefined
521
+ [ Opcodes.local_get, iTmp ],
522
+ ...number(0, Valtype.i32),
523
+ [ Opcodes.i32_lt_s ],
524
+
525
+ [ Opcodes.local_get, iTmp ],
526
+ ...length.getCachedI32(),
527
+ [ Opcodes.i32_ge_s ],
528
+ [ Opcodes.i32_or ],
529
+
530
+ [ Opcodes.if, Blocktype.void ],
531
+ ...number(UNDEFINED),
532
+ [ Opcodes.br, 1 ],
533
+ [ Opcodes.end ],
534
+
535
+ [ Opcodes.local_get, iTmp ],
536
+
537
+ ...pointer,
538
+ [ Opcodes.i32_add ],
539
+
540
+ // load current string ind {arg}
541
+ [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
542
+
543
+ // store to new string ind 0
544
+ [ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
545
+
546
+ // return new string (pointer)
547
+ ...number(newPointer)
548
+ ];
549
+ },
550
+
551
+ // todo: out of bounds properly
552
+ charAt: (pointer, length, wIndex, _1, _2, arrayShell) => {
553
+ const [ newOut, newPointer ] = arrayShell(1, 'i8');
554
+
555
+ return [
556
+ // setup new/out array
557
+ ...newOut,
558
+ [ Opcodes.drop ],
559
+
560
+ ...number(0, Valtype.i32), // base 0 for store later
561
+
562
+ ...wIndex,
563
+ Opcodes.i32_to,
564
+
565
+ ...pointer,
566
+ [ Opcodes.i32_add ],
567
+
568
+ // load current string ind {arg}
569
+ [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
570
+
571
+ // store to new string ind 0
572
+ [ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
573
+
574
+ // return new string (page)
575
+ ...number(newPointer)
576
+ ];
577
+ },
578
+
579
+ charCodeAt: (pointer, length, wIndex, iTmp) => {
580
+ return [
581
+ ...wIndex,
582
+ Opcodes.i32_to,
583
+
584
+ ...(zeroChecks.charcodeat ? [] : [
585
+ [ Opcodes.local_set, iTmp ],
586
+
587
+ // index < 0
588
+ ...(noUnlikelyChecks ? [] : [
589
+ [ Opcodes.local_get, iTmp ],
590
+ ...number(0, Valtype.i32),
591
+ [ Opcodes.i32_lt_s ],
592
+ ]),
593
+
594
+ // index >= length
595
+ [ Opcodes.local_get, iTmp ],
596
+ ...length.getCachedI32(),
597
+ [ Opcodes.i32_ge_s ],
598
+
599
+ ...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
600
+ [ Opcodes.if, Blocktype.void ],
601
+ ...number(valtype === 'i32' ? -1 : NaN),
602
+ [ Opcodes.br, 1 ],
603
+ [ Opcodes.end ],
604
+
605
+ [ Opcodes.local_get, iTmp ],
606
+ ]),
607
+
608
+ ...pointer,
609
+ [ Opcodes.i32_add ],
610
+
611
+ // load current string ind {arg}
612
+ [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
613
+ Opcodes.i32_from_u
614
+ ];
615
+ },
616
+
617
+ isWellFormed: () => {
618
+ return [
619
+ // we know it must be true as it is a bytestring lol
620
+ ...number(1)
621
+ ]
622
+ }
623
+ };
624
+
625
+ this[TYPES._bytestring].at.local = Valtype.i32;
626
+ this[TYPES._bytestring].at.returnType = TYPES._bytestring;
627
+ this[TYPES._bytestring].charAt.returnType = TYPES._bytestring;
628
+ this[TYPES._bytestring].charCodeAt.local = Valtype.i32;
629
+ this[TYPES._bytestring].charCodeAt.noPointerCache = zeroChecks.charcodeat;
630
+
631
+ this[TYPES._bytestring].isWellFormed.local = Valtype.i32;
632
+ this[TYPES._bytestring].isWellFormed.local2 = Valtype.i32;
633
+ this[TYPES._bytestring].isWellFormed.returnType = TYPES.boolean;
634
+ }
479
635
  };
@@ -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 = process.argv.includes('-compile-hints');
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,
@@ -95,7 +96,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
95
96
  // https://github.com/WebAssembly/design/issues/1473#issuecomment-1431274746
96
97
  const chSection = !compileHints ? [] : customSection(
97
98
  'compilationHints',
98
- // for now just do everything as optimise eager
99
+ // for now just do everything as optimize eager
99
100
  encodeVector(funcs.map(_ => chHint(0x02, 0x02, 0x02)))
100
101
  );
101
102
 
@@ -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 (process.argv.includes('-always-memory') && pages.size === 0) pages.set('-always-memory', 0);
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 (process.argv.includes('-sections')) console.log({
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)),
@@ -32,17 +32,16 @@ export const Opcodes = {
32
32
  throw: 0x08,
33
33
  rethrow: 0x09,
34
34
 
35
- call: 0x10,
36
- call_indirect: 0x11,
37
- return_call: 0x12,
38
- return_call_indirect: 0x13,
39
-
40
35
  end: 0x0b,
41
36
  br: 0x0c,
42
37
  br_if: 0x0d,
43
38
  br_table: 0x0e,
44
39
  return: 0x0f,
40
+
45
41
  call: 0x10,
42
+ call_indirect: 0x11,
43
+ return_call: 0x12,
44
+ return_call_indirect: 0x13,
46
45
 
47
46
  drop: 0x1a,
48
47
 
@@ -57,15 +56,26 @@ export const Opcodes = {
57
56
  i64_load: 0x29,
58
57
  f64_load: 0x2b,
59
58
 
59
+ i32_load8_s: 0x2c,
60
+ i32_load8_u: 0x2d,
60
61
  i32_load16_s: 0x2e,
61
62
  i32_load16_u: 0x2f,
62
63
 
63
- i32_store16: 0x3b,
64
+ i64_load8_s: 0x30,
65
+ i64_load8_u: 0x31,
66
+ i64_load16_s: 0x32,
67
+ i64_load16_u: 0x33,
64
68
 
65
69
  i32_store: 0x36,
66
70
  i64_store: 0x37,
67
71
  f64_store: 0x39,
68
72
 
73
+ i32_store8: 0x3a,
74
+ i32_store16: 0x3b,
75
+
76
+ i64_store8: 0x3c,
77
+ i64_store16: 0x3d,
78
+
69
79
  memory_grow: 0x40,
70
80
 
71
81
  i32_const: 0x41,
package/compiler/wrap.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import compile from './index.js';
2
2
  import decompile from './decompile.js';
3
- import fs from 'node:fs';
3
+ import { encodeVector, encodeLocal } from './encoding.js';
4
+ import Prefs from './prefs.js';
5
+ import { log } from './log.js';
4
6
 
5
7
  const bold = x => `\u001b[1m${x}\u001b[0m`;
6
8
 
@@ -18,7 +20,8 @@ const TYPES = {
18
20
 
19
21
  // internal
20
22
  [internalTypeBase]: '_array',
21
- [internalTypeBase + 1]: '_regexp'
23
+ [internalTypeBase + 1]: '_regexp',
24
+ [internalTypeBase + 2]: '_bytestring'
22
25
  };
23
26
 
24
27
  export default async (source, flags = [ 'module' ], customImports = {}, print = str => process.stdout.write(str)) => {
@@ -29,20 +32,110 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
29
32
 
30
33
  if (source.includes('export function')) flags.push('module');
31
34
 
32
- fs.writeFileSync('out.wasm', Buffer.from(wasm));
35
+ // (await import('node:fs')).writeFileSync('out.wasm', Buffer.from(wasm));
33
36
 
34
37
  times.push(performance.now() - t1);
35
38
  if (flags.includes('info')) console.log(bold(`compiled in ${times[0].toFixed(2)}ms`));
36
39
 
37
40
  const t2 = performance.now();
38
- const { instance } = await WebAssembly.instantiate(wasm, {
39
- '': {
40
- p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
41
- c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
42
- t: _ => performance.now(),
43
- ...customImports
41
+
42
+ let instance;
43
+ try {
44
+ let wasmEngine = WebAssembly;
45
+ if (Prefs.asur) {
46
+ log.warning('wrap', 'using our !experimental! asur wasm engine instead of host to run');
47
+ wasmEngine = await import('../asur/index.js');
48
+ }
49
+
50
+ 0, { instance } = await wasmEngine.instantiate(wasm, {
51
+ '': {
52
+ p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
53
+ c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
54
+ t: _ => performance.now(),
55
+ ...customImports
56
+ }
57
+ });
58
+ } catch (e) {
59
+ // only backtrace for runner, not test262/etc
60
+ if (!process.argv[1].includes('/runner')) throw e;
61
+
62
+ const funcInd = parseInt(e.message.match(/function #([0-9]+) /)[1]);
63
+ const blobOffset = parseInt(e.message.split('@')[1]);
64
+
65
+ // convert blob offset -> function wasm offset.
66
+ // this is not good code and is somewhat duplicated
67
+ // I just want it to work for debugging, I don't care about perf/yes
68
+
69
+ const func = funcs.find(x => x.index === funcInd);
70
+ const locals = Object.values(func.locals).sort((a, b) => a.idx - b.idx).slice(func.params.length).sort((a, b) => a.idx - b.idx);
71
+
72
+ let localDecl = [], typeCount = 0, lastType;
73
+ for (let i = 0; i < locals.length; i++) {
74
+ const local = locals[i];
75
+ if (i !== 0 && local.type !== lastType) {
76
+ localDecl.push(encodeLocal(typeCount, lastType));
77
+ typeCount = 0;
78
+ }
79
+
80
+ typeCount++;
81
+ lastType = local.type;
82
+ }
83
+
84
+ if (typeCount !== 0) localDecl.push(encodeLocal(typeCount, lastType));
85
+
86
+ const toFind = encodeVector(localDecl).concat(func.wasm.flat().filter(x => x != null && x <= 0xff).slice(0, 40));
87
+
88
+ let i = 0;
89
+ for (; i < wasm.length; i++) {
90
+ let mismatch = false;
91
+ for (let j = 0; j < toFind.length; j++) {
92
+ if (wasm[i + j] !== toFind[j]) {
93
+ mismatch = true;
94
+ break;
95
+ }
96
+ }
97
+
98
+ if (!mismatch) break;
99
+ }
100
+
101
+ if (i === wasm.length) throw e;
102
+
103
+ const offset = (blobOffset - i) + encodeVector(localDecl).length;
104
+
105
+ let cumLen = 0;
106
+ i = 0;
107
+ for (; i < func.wasm.length; i++) {
108
+ cumLen += func.wasm[i].filter(x => x != null && x <= 0xff).length;
109
+ if (cumLen === offset) break;
44
110
  }
45
- });
111
+
112
+ if (cumLen !== offset) throw e;
113
+
114
+ i -= 1;
115
+
116
+ console.log(`\x1B[35m\x1B[1mporffor backtrace\u001b[0m`);
117
+
118
+ console.log('\x1B[4m' + func.name + '\x1B[0m');
119
+
120
+ const surrounding = 6;
121
+
122
+ const decomp = decompile(func.wasm.slice(i - surrounding, i + surrounding + 1), '', 0, func.locals, func.params, func.returns, funcs, globals, exceptions).slice(0, -1).split('\n');
123
+
124
+ const noAnsi = s => s.replace(/\u001b\[[0-9]+m/g, '');
125
+ let longest = 0;
126
+ for (let j = 0; j < decomp.length; j++) {
127
+ longest = Math.max(longest, noAnsi(decomp[j]).length);
128
+ }
129
+
130
+ const middle = Math.floor(decomp.length / 2);
131
+ decomp[middle] = `\x1B[47m\x1B[30m${noAnsi(decomp[middle])}${'\u00a0'.repeat(longest - noAnsi(decomp[middle]).length)}\x1B[0m`;
132
+
133
+ console.log('\x1B[90m...\x1B[0m');
134
+ console.log(decomp.join('\n'));
135
+ console.log('\x1B[90m...\x1B[0m\n');
136
+
137
+ throw e;
138
+ }
46
139
 
47
140
  times.push(performance.now() - t2);
48
141
  if (flags.includes('info')) console.log(`instantiated in ${times[1].toFixed(2)}ms`);
@@ -95,10 +188,18 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
95
188
  return Array.from(new Uint16Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
96
189
  }
97
190
 
191
+ case '_bytestring': {
192
+ const pointer = ret;
193
+ const length = new Int32Array(memory.buffer, pointer, 1);
194
+
195
+ return Array.from(new Uint8Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
196
+ }
197
+
98
198
  case 'function': {
99
199
  // wasm func index, including all imports
100
200
  const func = funcs.find(x => (x.originalIndex ?? x.index) === ret);
101
- if (!func) return ret;
201
+ // if (!func) return ret;
202
+ if (!func) return function () {};
102
203
 
103
204
  // make fake empty func for repl/etc
104
205
  return {[func.name]() {}}[func.name];
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.2.0-5e33105",
4
+ "version": "0.2.0-6aff0fa",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "dependencies": {
package/porf ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ node runner/index.js "$@"
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 (globalThis.regexLog) {
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);
package/runner/index.js CHANGED
@@ -3,6 +3,8 @@
3
3
  import compile from '../compiler/wrap.js';
4
4
  import fs from 'node:fs';
5
5
 
6
+ const start = performance.now();
7
+
6
8
  if (process.argv.includes('-compile-hints')) {
7
9
  const v8 = await import('node:v8');
8
10
  v8.setFlagsFromString(`--experimental-wasm-compilation-hints`);
@@ -15,9 +17,28 @@ if (process.argv.includes('-compile-hints')) {
15
17
  // --experimental-wasm-return-call (on by default)
16
18
  }
17
19
 
18
- const file = process.argv.slice(2).find(x => x[0] !== '-');
20
+ let file = process.argv.slice(2).find(x => x[0] !== '-');
21
+ if (['run', 'wasm', 'native', 'c', 'profile'].includes(file)) {
22
+ if (file === 'profile') {
23
+ process.argv.splice(process.argv.indexOf(file), 1);
24
+ await import('./profiler.js');
25
+ await new Promise(() => {});
26
+ }
27
+
28
+ if (['wasm', 'native', 'c'].includes(file)) {
29
+ process.argv.push(`-target=${file}`);
30
+ }
31
+
32
+ file = process.argv.slice(process.argv.indexOf(file) + 1).find(x => x[0] !== '-');
33
+
34
+ const nonOptOutFile = process.argv.slice(process.argv.indexOf(file) + 1).find(x => x[0] !== '-');
35
+ if (nonOptOutFile) {
36
+ process.argv.push(`-o=${nonOptOutFile}`);
37
+ }
38
+ }
39
+
19
40
  if (!file) {
20
- if (process.argv.includes('-v')) {
41
+ if (process.argv.includes('-v') || process.argv.includes('--version')) {
21
42
  // just print version
22
43
  console.log((await import('./version.js')).default);
23
44
  process.exit(0);
@@ -52,4 +73,6 @@ try {
52
73
  } catch (e) {
53
74
  if (cache) process.stdout.write(cache);
54
75
  console.error(process.argv.includes('-i') ? e : `${e.constructor.name}: ${e.message}`);
55
- }
76
+ }
77
+
78
+ if (process.argv.includes('-t')) console.log(`\n\ntotal time: ${(performance.now() - start).toFixed(2)}ms`);