porffor 0.2.0-a759814 → 0.2.0-af678f0

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.
@@ -15,7 +15,7 @@ export default (wasm, name = '', ind = 0, locals = {}, params = [], returns = []
15
15
  if (name) out += `${makeSignature(params, returns)} ;; $${name} (${ind})\n`;
16
16
 
17
17
  const justLocals = Object.values(locals).sort((a, b) => a.idx - b.idx).slice(params.length);
18
- if (justLocals.length > 0) out += ` local ${justLocals.map(x => invValtype[x.type]).join(' ')}\n`;
18
+ if (name && justLocals.length > 0) out += ` local ${justLocals.map(x => invValtype[x.type]).join(' ')}\n`;
19
19
 
20
20
  let i = -1, lastInst;
21
21
  let byte = 0;
@@ -32,7 +32,7 @@ export default (wasm, name = '', ind = 0, locals = {}, params = [], returns = []
32
32
  inst = [ [ inst[0], inst[1] ], ...inst.slice(2) ];
33
33
  }
34
34
 
35
- if (inst[0] === Opcodes.end || inst[0] === Opcodes.else || inst[0] === Opcodes.catch_all) depth--;
35
+ if (depth > 0 && (inst[0] === Opcodes.end || inst[0] === Opcodes.else || inst[0] === Opcodes.catch_all)) depth--;
36
36
 
37
37
  out += ' '.repeat(Math.max(0, depth * 2));
38
38
 
@@ -119,7 +119,7 @@ export default (wasm, name = '', ind = 0, locals = {}, params = [], returns = []
119
119
  export const highlightAsm = asm => asm
120
120
  .replace(/(local|global|memory)\.[^\s]*/g, _ => `\x1B[31m${_}\x1B[0m`)
121
121
  .replace(/(i(8|16|32|64)x[0-9]+|v128)(\.[^\s]*)?/g, _ => `\x1B[34m${_}\x1B[0m`)
122
- .replace(/[^m](i32|i64|f32|f64|drop)(\.[^\s]*)?/g, _ => `${_[0]}\x1B[36m${_.slice(1)}\x1B[0m`)
122
+ .replace(/(i32|i64|f32|f64|drop)(\.[^\s]*)?/g, _ => `\x1B[36m${_}\x1B[0m`)
123
123
  .replace(/(return_call|call|br_if|br|return|rethrow|throw)/g, _ => `\x1B[35m${_}\x1B[0m`)
124
124
  .replace(/(block|loop|if|end|else|try|catch_all|catch|delegate)/g, _ => `\x1B[95m${_}\x1B[0m`)
125
125
  .replace(/unreachable/g, _ => `\x1B[91m${_}\x1B[0m`)
package/compiler/index.js CHANGED
@@ -52,7 +52,7 @@ export default (code, flags) => {
52
52
  if (process.argv.includes('-funcs')) logFuncs(funcs, globals, exceptions);
53
53
 
54
54
  const t2 = performance.now();
55
- opt(funcs, globals, pages);
55
+ opt(funcs, globals, pages, tags);
56
56
  if (flags.includes('info')) console.log(`3. optimized code in ${(performance.now() - t2).toFixed(2)}ms`);
57
57
 
58
58
  if (process.argv.includes('-opt-funcs')) logFuncs(funcs, globals, exceptions);
@@ -68,11 +68,17 @@ export default (code, flags) => {
68
68
  console.log([...pages.keys()].map(x => `\x1B[36m - ${x}\x1B[0m`).join('\n') + '\n');
69
69
  }
70
70
 
71
- const out = { wasm: sections, funcs, globals, tags, exceptions, pages };
71
+ const out = { wasm: sections, funcs, globals, tags, exceptions, pages, data };
72
72
 
73
73
  const target = getArg('target') ?? getArg('t') ?? 'wasm';
74
74
  const outFile = getArg('o');
75
75
 
76
+ if (target === 'wasm' && outFile) {
77
+ writeFileSync(outFile, Buffer.from(sections));
78
+
79
+ if (process.version) process.exit();
80
+ }
81
+
76
82
  if (target === 'c') {
77
83
  const c = toc(out);
78
84
  out.c = c;
@@ -87,11 +93,16 @@ export default (code, flags) => {
87
93
  }
88
94
 
89
95
  if (target === 'native') {
90
- const compiler = getArg('compiler') ?? 'clang';
96
+ let compiler = getArg('compiler') ?? 'clang';
91
97
  const cO = getArg('cO') ?? 'Ofast';
92
98
 
99
+ if (compiler === 'zig') compiler = [ 'zig', 'cc' ];
100
+ else compiler = [ compiler ];
101
+
93
102
  const tmpfile = 'tmp.c';
94
- const args = [ compiler, tmpfile, '-o', outFile ?? (process.platform === 'win32' ? 'out.exe' : 'out'), '-' + cO, '-march=native' ];
103
+ // 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' ];
104
+ // const args = [ ...compiler, tmpfile, '-o', outFile ?? (process.platform === 'win32' ? 'out.exe' : 'out'), '-' + cO, '-march=native', '-s', '-ffast-math', '-fno-exceptions', '-target', 'x86_64-linux' ];
105
+ const args = [ ...compiler, tmpfile, '-o', outFile ?? (process.platform === 'win32' ? 'out.exe' : 'out'), '-' + cO, '-march=native', '-s', '-ffast-math', '-fno-exceptions' ];
95
106
 
96
107
  const c = toc(out);
97
108
  writeFileSync(tmpfile, c);
package/compiler/opt.js CHANGED
@@ -11,7 +11,7 @@ const performWasmOp = (op, a, b) => {
11
11
  }
12
12
  };
13
13
 
14
- export default (funcs, globals, pages) => {
14
+ export default (funcs, globals, pages, tags) => {
15
15
  const optLevel = parseInt(process.argv.find(x => x.startsWith('-O'))?.[2] ?? 1);
16
16
  if (optLevel === 0) return;
17
17
 
@@ -99,6 +99,8 @@ export default (funcs, globals, pages) => {
99
99
 
100
100
  if (process.argv.includes('-opt-inline-only')) return;
101
101
 
102
+ const tagUse = tags.reduce((acc, x) => { acc[x.idx] = 0; return acc; }, {});
103
+
102
104
  // wasm transform pass
103
105
  for (const f of funcs) {
104
106
  const wasm = f.wasm;
@@ -127,6 +129,8 @@ export default (funcs, globals, pages) => {
127
129
  if (inst[0] === Opcodes.local_get) getCount[inst[1]]++;
128
130
  if (inst[0] === Opcodes.local_set || inst[0] === Opcodes.local_tee) setCount[inst[1]]++;
129
131
 
132
+ if (inst[0] === Opcodes.throw) tagUse[inst[1]]++;
133
+
130
134
  if (inst[0] === Opcodes.block) {
131
135
  // remove unneeded blocks (no brs inside)
132
136
  // block
@@ -143,7 +147,7 @@ export default (funcs, globals, pages) => {
143
147
  depth--;
144
148
  if (depth <= 0) break;
145
149
  }
146
- if (op === Opcodes.br || op === Opcodes.br_if) {
150
+ if (op === Opcodes.br || op === Opcodes.br_if || op === Opcodes.br_table) {
147
151
  hasBranch = true;
148
152
  break;
149
153
  }
@@ -188,6 +192,7 @@ export default (funcs, globals, pages) => {
188
192
  let missing = false;
189
193
  if (type === 'Array') missing = !pages.hasArray;
190
194
  if (type === 'String') missing = !pages.hasString;
195
+ if (type === 'ByteString') missing = !pages.hasByteString;
191
196
 
192
197
  if (missing) {
193
198
  let j = i, depth = 0;
@@ -235,7 +240,7 @@ export default (funcs, globals, pages) => {
235
240
  }
236
241
 
237
242
  // remove setting last type if it is never gotten
238
- if (!f.gotLastType && inst[0] === Opcodes.local_set && inst[1] === lastType.idx) {
243
+ if (!f.gotLastType && inst[0] === Opcodes.local_set && inst[1] === lastType?.idx) {
239
244
  // replace this inst with drop
240
245
  wasm.splice(i, 1, [ Opcodes.drop ]); // remove this and last inst
241
246
  if (i > 0) i--;
@@ -541,5 +546,12 @@ export default (funcs, globals, pages) => {
541
546
  }
542
547
  }
543
548
 
549
+ for (const x in tagUse) {
550
+ if (tagUse[x] === 0) {
551
+ const el = tags.find(y => y.idx === x);
552
+ tags.splice(tags.indexOf(el), 1);
553
+ }
554
+ }
555
+
544
556
  // return funcs;
545
557
  };
@@ -16,7 +16,8 @@ const TYPES = {
16
16
 
17
17
  // these are not "typeof" types but tracked internally
18
18
  _array: 0x10,
19
- _regexp: 0x11
19
+ _regexp: 0x11,
20
+ _bytestring: 0x12
20
21
  };
21
22
 
22
23
  // todo: turn these into built-ins once arrays and these become less hacky
@@ -71,7 +72,7 @@ export const PrototypeFuncs = function() {
71
72
  ],
72
73
 
73
74
  // todo: only for 1 argument
74
- push: (pointer, length, wNewMember) => [
75
+ push: (pointer, length, wNewMember, _1, _2, _3, unusedValue) => [
75
76
  // get memory offset of array at last index (length)
76
77
  ...length.getCachedI32(),
77
78
  ...number(ValtypeSize[valtype], Valtype.i32),
@@ -92,22 +93,28 @@ export const PrototypeFuncs = function() {
92
93
  ...number(1, Valtype.i32),
93
94
  [ Opcodes.i32_add ],
94
95
 
95
- ...length.setCachedI32(),
96
- ...length.getCachedI32(),
96
+ ...(unusedValue() ? [] : [
97
+ ...length.setCachedI32(),
98
+ ...length.getCachedI32(),
99
+ ])
97
100
  ]),
98
101
 
99
- ...length.getCachedI32(),
100
- Opcodes.i32_from_u
102
+ ...(unusedValue() ? [] : [
103
+ ...length.getCachedI32(),
104
+ Opcodes.i32_from_u
105
+ ])
101
106
 
102
107
  // ...length.get()
103
108
  ],
104
109
 
105
- pop: (pointer, length) => [
110
+ pop: (pointer, length, _1, _2, _3, _4, unusedValue) => [
106
111
  // if length == 0, noop
107
112
  ...length.getCachedI32(),
108
113
  [ Opcodes.i32_eqz ],
109
114
  [ Opcodes.if, Blocktype.void ],
110
- ...number(UNDEFINED),
115
+ ...(unusedValue() ? [] : [
116
+ ...number(UNDEFINED),
117
+ ]),
111
118
  [ Opcodes.br, 1 ],
112
119
  [ Opcodes.end ],
113
120
 
@@ -119,19 +126,23 @@ export const PrototypeFuncs = function() {
119
126
  ...number(1, Valtype.i32),
120
127
  [ Opcodes.i32_sub ],
121
128
 
122
- ...length.setCachedI32(),
123
- ...length.getCachedI32(),
129
+ ...(unusedValue() ? [] : [
130
+ ...length.setCachedI32(),
131
+ ...length.getCachedI32(),
132
+ ])
124
133
  ]),
125
134
 
126
135
  // load last element
127
- ...length.getCachedI32(),
128
- ...number(ValtypeSize[valtype], Valtype.i32),
129
- [ Opcodes.i32_mul ],
136
+ ...(unusedValue() ? [] : [
137
+ ...length.getCachedI32(),
138
+ ...number(ValtypeSize[valtype], Valtype.i32),
139
+ [ Opcodes.i32_mul ],
130
140
 
131
- ...pointer,
132
- [ Opcodes.i32_add ],
141
+ ...pointer,
142
+ [ Opcodes.i32_add ],
133
143
 
134
- [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(ValtypeSize.i32) ]
144
+ [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(ValtypeSize.i32) ]
145
+ ])
135
146
  ],
136
147
 
137
148
  shift: (pointer, length) => [
@@ -472,8 +483,152 @@ export const PrototypeFuncs = function() {
472
483
  this[TYPES.string].at.returnType = TYPES.string;
473
484
  this[TYPES.string].charAt.returnType = TYPES.string;
474
485
  this[TYPES.string].charCodeAt.local = Valtype.i32;
486
+ this[TYPES.string].charCodeAt.noPointerCache = zeroChecks.charcodeat;
475
487
 
476
488
  this[TYPES.string].isWellFormed.local = Valtype.i32;
477
489
  this[TYPES.string].isWellFormed.local2 = Valtype.i32;
478
490
  this[TYPES.string].isWellFormed.returnType = TYPES.boolean;
491
+
492
+ if (process.argv.includes('-bytestring')) {
493
+ this[TYPES._bytestring] = {
494
+ at: (pointer, length, wIndex, iTmp, _, arrayShell) => {
495
+ const [ newOut, newPointer ] = arrayShell(1, 'i16');
496
+
497
+ return [
498
+ // setup new/out array
499
+ ...newOut,
500
+ [ Opcodes.drop ],
501
+
502
+ ...number(0, Valtype.i32), // base 0 for store later
503
+
504
+ ...wIndex,
505
+ Opcodes.i32_to_u,
506
+ [ Opcodes.local_tee, iTmp ],
507
+
508
+ // if index < 0: access index + array length
509
+ ...number(0, Valtype.i32),
510
+ [ Opcodes.i32_lt_s ],
511
+ [ Opcodes.if, Blocktype.void ],
512
+ [ Opcodes.local_get, iTmp ],
513
+ ...length.getCachedI32(),
514
+ [ Opcodes.i32_add ],
515
+ [ Opcodes.local_set, iTmp ],
516
+ [ Opcodes.end ],
517
+
518
+ // if still < 0 or >= length: return undefined
519
+ [ Opcodes.local_get, iTmp ],
520
+ ...number(0, Valtype.i32),
521
+ [ Opcodes.i32_lt_s ],
522
+
523
+ [ Opcodes.local_get, iTmp ],
524
+ ...length.getCachedI32(),
525
+ [ Opcodes.i32_ge_s ],
526
+ [ Opcodes.i32_or ],
527
+
528
+ [ Opcodes.if, Blocktype.void ],
529
+ ...number(UNDEFINED),
530
+ [ Opcodes.br, 1 ],
531
+ [ Opcodes.end ],
532
+
533
+ [ Opcodes.local_get, iTmp ],
534
+
535
+ ...pointer,
536
+ [ Opcodes.i32_add ],
537
+
538
+ // load current string ind {arg}
539
+ [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
540
+
541
+ // store to new string ind 0
542
+ [ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
543
+
544
+ // return new string (pointer)
545
+ ...number(newPointer)
546
+ ];
547
+ },
548
+
549
+ // todo: out of bounds properly
550
+ charAt: (pointer, length, wIndex, _1, _2, arrayShell) => {
551
+ const [ newOut, newPointer ] = arrayShell(1, 'i16');
552
+
553
+ return [
554
+ // setup new/out array
555
+ ...newOut,
556
+ [ Opcodes.drop ],
557
+
558
+ ...number(0, Valtype.i32), // base 0 for store later
559
+
560
+ ...wIndex,
561
+
562
+ Opcodes.i32_to,
563
+
564
+ ...pointer,
565
+ [ Opcodes.i32_add ],
566
+
567
+ // load current string ind {arg}
568
+ [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
569
+
570
+ // store to new string ind 0
571
+ [ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
572
+
573
+ // return new string (page)
574
+ ...number(newPointer)
575
+ ];
576
+ },
577
+
578
+ charCodeAt: (pointer, length, wIndex, iTmp) => {
579
+ return [
580
+ ...wIndex,
581
+ Opcodes.i32_to,
582
+
583
+ ...(zeroChecks.charcodeat ? [] : [
584
+ [ Opcodes.local_set, iTmp ],
585
+
586
+ // index < 0
587
+ ...(noUnlikelyChecks ? [] : [
588
+ [ Opcodes.local_get, iTmp ],
589
+ ...number(0, Valtype.i32),
590
+ [ Opcodes.i32_lt_s ],
591
+ ]),
592
+
593
+ // index >= length
594
+ [ Opcodes.local_get, iTmp ],
595
+ ...length.getCachedI32(),
596
+ [ Opcodes.i32_ge_s ],
597
+
598
+ ...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
599
+ [ Opcodes.if, Blocktype.void ],
600
+ ...number(NaN),
601
+ [ Opcodes.br, 1 ],
602
+ [ Opcodes.end ],
603
+
604
+ [ Opcodes.local_get, iTmp ],
605
+ ]),
606
+
607
+ ...pointer,
608
+ [ Opcodes.i32_add ],
609
+
610
+ // load current string ind {arg}
611
+ [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
612
+ Opcodes.i32_from_u
613
+ ];
614
+ },
615
+
616
+ isWellFormed: () => {
617
+ return [
618
+ // we know it must be true as it is a bytestring lol
619
+ ...number(1)
620
+ ]
621
+ }
622
+ };
623
+
624
+ this[TYPES._bytestring].at.local = Valtype.i32;
625
+ this[TYPES._bytestring].at.returnType = TYPES._bytestring;
626
+ this[TYPES._bytestring].charAt.returnType = TYPES._bytestring;
627
+ this[TYPES._bytestring].charCodeAt.local = Valtype.i32;
628
+ this[TYPES._bytestring].charCodeAt.noPointerCache = zeroChecks.charcodeat;
629
+
630
+ this[TYPES._bytestring].isWellFormed.local = Valtype.i32;
631
+ this[TYPES._bytestring].isWellFormed.local2 = Valtype.i32;
632
+ this[TYPES._bytestring].isWellFormed.returnType = TYPES.boolean;
633
+ }
479
634
  };
@@ -150,7 +150,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
150
150
 
151
151
  if (typeCount !== 0) localDecl.push(encodeLocal(typeCount, lastType));
152
152
 
153
- return encodeVector([ ...encodeVector(localDecl), ...x.wasm.flat().filter(x => x <= 0xff), Opcodes.end ]);
153
+ return encodeVector([ ...encodeVector(localDecl), ...x.wasm.flat().filter(x => x != null && x <= 0xff), Opcodes.end ]);
154
154
  }))
155
155
  );
156
156
 
@@ -32,8 +32,6 @@ export const Opcodes = {
32
32
  throw: 0x08,
33
33
  rethrow: 0x09,
34
34
 
35
- return: 0x0F,
36
-
37
35
  call: 0x10,
38
36
  call_indirect: 0x11,
39
37
  return_call: 0x12,
@@ -42,7 +40,10 @@ export const Opcodes = {
42
40
  end: 0x0b,
43
41
  br: 0x0c,
44
42
  br_if: 0x0d,
43
+ br_table: 0x0e,
44
+ return: 0x0f,
45
45
  call: 0x10,
46
+
46
47
  drop: 0x1a,
47
48
 
48
49
  local_get: 0x20,
@@ -56,9 +57,12 @@ export const Opcodes = {
56
57
  i64_load: 0x29,
57
58
  f64_load: 0x2b,
58
59
 
60
+ i32_load8_s: 0x2c,
61
+ i32_load8_u: 0x2d,
59
62
  i32_load16_s: 0x2e,
60
63
  i32_load16_u: 0x2f,
61
64
 
65
+ i32_store8: 0x3a,
62
66
  i32_store16: 0x3b,
63
67
 
64
68
  i32_store: 0x36,
package/compiler/wrap.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import compile from './index.js';
2
2
  import decompile from './decompile.js';
3
+ import { encodeVector, encodeLocal } from './encoding.js';
3
4
  // import fs from 'node:fs';
4
5
 
5
6
  const bold = x => `\u001b[1m${x}\u001b[0m`;
@@ -18,7 +19,8 @@ const TYPES = {
18
19
 
19
20
  // internal
20
21
  [internalTypeBase]: '_array',
21
- [internalTypeBase + 1]: '_regexp'
22
+ [internalTypeBase + 1]: '_regexp',
23
+ [internalTypeBase + 2]: '_bytestring'
22
24
  };
23
25
 
24
26
  export default async (source, flags = [ 'module' ], customImports = {}, print = str => process.stdout.write(str)) => {
@@ -35,14 +37,98 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
35
37
  if (flags.includes('info')) console.log(bold(`compiled in ${times[0].toFixed(2)}ms`));
36
38
 
37
39
  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
40
+
41
+ let instance;
42
+ try {
43
+ 0, { instance } = await WebAssembly.instantiate(wasm, {
44
+ '': {
45
+ p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
46
+ c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
47
+ t: _ => performance.now(),
48
+ ...customImports
49
+ }
50
+ });
51
+ } catch (e) {
52
+ // only backtrace for runner, not test262/etc
53
+ if (!process.argv[1].includes('/runner')) throw e;
54
+
55
+ const funcInd = parseInt(e.message.match(/function #([0-9]+) /)[1]);
56
+ const blobOffset = parseInt(e.message.split('@')[1]);
57
+
58
+ // convert blob offset -> function wasm offset.
59
+ // this is not good code and is somewhat duplicated
60
+ // I just want it to work for debugging, I don't care about perf/yes
61
+
62
+ const func = funcs.find(x => x.index === funcInd);
63
+ const locals = Object.values(func.locals).sort((a, b) => a.idx - b.idx).slice(func.params.length).sort((a, b) => a.idx - b.idx);
64
+
65
+ let localDecl = [], typeCount = 0, lastType;
66
+ for (let i = 0; i < locals.length; i++) {
67
+ const local = locals[i];
68
+ if (i !== 0 && local.type !== lastType) {
69
+ localDecl.push(encodeLocal(typeCount, lastType));
70
+ typeCount = 0;
71
+ }
72
+
73
+ typeCount++;
74
+ lastType = local.type;
75
+ }
76
+
77
+ if (typeCount !== 0) localDecl.push(encodeLocal(typeCount, lastType));
78
+
79
+ const toFind = encodeVector(localDecl).concat(func.wasm.flat().filter(x => x != null && x <= 0xff).slice(0, 40));
80
+
81
+ let i = 0;
82
+ for (; i < wasm.length; i++) {
83
+ let mismatch = false;
84
+ for (let j = 0; j < toFind.length; j++) {
85
+ if (wasm[i + j] !== toFind[j]) {
86
+ mismatch = true;
87
+ break;
88
+ }
89
+ }
90
+
91
+ if (!mismatch) break;
92
+ }
93
+
94
+ if (i === wasm.length) throw e;
95
+
96
+ const offset = (blobOffset - i) + encodeVector(localDecl).length;
97
+
98
+ let cumLen = 0;
99
+ i = 0;
100
+ for (; i < func.wasm.length; i++) {
101
+ cumLen += func.wasm[i].filter(x => x != null && x <= 0xff).length;
102
+ if (cumLen === offset) break;
103
+ }
104
+
105
+ if (cumLen !== offset) throw e;
106
+
107
+ i -= 1;
108
+
109
+ console.log(`\x1B[35m\x1B[1mporffor backtrace\u001b[0m`);
110
+
111
+ console.log('\x1B[4m' + func.name + '\x1B[0m');
112
+
113
+ const surrounding = 6;
114
+
115
+ 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');
116
+
117
+ const noAnsi = s => s.replace(/\u001b\[[0-9]+m/g, '');
118
+ let longest = 0;
119
+ for (let j = 0; j < decomp.length; j++) {
120
+ longest = Math.max(longest, noAnsi(decomp[j]).length);
44
121
  }
45
- });
122
+
123
+ const middle = Math.floor(decomp.length / 2);
124
+ decomp[middle] = `\x1B[47m\x1B[30m${noAnsi(decomp[middle])}${'\u00a0'.repeat(longest - noAnsi(decomp[middle]).length)}\x1B[0m`;
125
+
126
+ console.log('\x1B[90m...\x1B[0m');
127
+ console.log(decomp.join('\n'));
128
+ console.log('\x1B[90m...\x1B[0m\n');
129
+
130
+ throw e;
131
+ }
46
132
 
47
133
  times.push(performance.now() - t2);
48
134
  if (flags.includes('info')) console.log(`instantiated in ${times[1].toFixed(2)}ms`);
@@ -95,6 +181,13 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
95
181
  return Array.from(new Uint16Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
96
182
  }
97
183
 
184
+ case '_bytestring': {
185
+ const pointer = ret;
186
+ const length = new Int32Array(memory.buffer, pointer, 1);
187
+
188
+ return Array.from(new Uint8Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
189
+ }
190
+
98
191
  case 'function': {
99
192
  // wasm func index, including all imports
100
193
  const func = funcs.find(x => (x.originalIndex ?? x.index) === ret);
package/filesize.cmd ADDED
@@ -0,0 +1,2 @@
1
+ @echo off
2
+ echo %~z1
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-a759814",
4
+ "version": "0.2.0-af678f0",
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/runner/index.js CHANGED
@@ -15,9 +15,22 @@ if (process.argv.includes('-compile-hints')) {
15
15
  // --experimental-wasm-return-call (on by default)
16
16
  }
17
17
 
18
- const file = process.argv.slice(2).find(x => x[0] !== '-');
18
+ let file = process.argv.slice(2).find(x => x[0] !== '-');
19
+ if (['run', 'wasm', 'native', 'c'].includes(file)) {
20
+ if (['wasm', 'native', 'c'].includes(file)) {
21
+ process.argv.push(`-target=${file}`);
22
+ }
23
+
24
+ file = process.argv.slice(process.argv.indexOf(file) + 1).find(x => x[0] !== '-');
25
+
26
+ const nonOptOutFile = process.argv.slice(process.argv.indexOf(file) + 1).find(x => x[0] !== '-');
27
+ if (nonOptOutFile) {
28
+ process.argv.push(`-o=${nonOptOutFile}`);
29
+ }
30
+ }
31
+
19
32
  if (!file) {
20
- if (process.argv.includes('-v')) {
33
+ if (process.argv.includes('-v') || process.argv.includes('--version')) {
21
34
  // just print version
22
35
  console.log((await import('./version.js')).default);
23
36
  process.exit(0);