porffor 0.0.0-425ea20 → 0.0.0-48403fd

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.
@@ -18,6 +18,7 @@ export default (wasm, name = '', ind = 0, locals = {}, params = [], returns = []
18
18
  if (justLocals.length > 0) out += ` local ${justLocals.map(x => invValtype[x.type]).join(' ')}\n`;
19
19
 
20
20
  let i = 0, lastInst;
21
+ let byte = 0;
21
22
  for (let inst of wasm.concat(name ? [ [ Opcodes.end ] ] : [])) {
22
23
  if (inst[0] === null) continue;
23
24
 
@@ -33,8 +34,18 @@ export default (wasm, name = '', ind = 0, locals = {}, params = [], returns = []
33
34
  if (inst[0] === Opcodes.end || inst[0] === Opcodes.else || inst[0] === Opcodes.catch_all) depth--;
34
35
 
35
36
  const opStr = invOpcodes[inst[0]];
36
- if (!opStr) console.log(`decomp: unknown op ${inst[0].toString(16)}`)
37
- out += /* ' '.repeat(3 - i.toString().length) + i + ' ' + */ ' '.repeat(Math.max(0, depth * 2)) + opStr.replace('_', '.').replace('return.', 'return_').replace('call.', 'call_').replace('br.', 'br_');
37
+ if (!opStr) {
38
+ console.log(`decomp: unknown op ${inst[0]?.toString?.(16)}`);
39
+ // out += `;; failed to decomp\n`;
40
+ continue;
41
+ }
42
+
43
+ // out += '0x' + byte.toString(10).padStart(2, '0');
44
+ byte += inst.length;
45
+
46
+ out += ' '.repeat(Math.max(0, depth * 2));
47
+
48
+ out += opStr.replace('_', '.').replace('return.', 'return_').replace('call.', 'call_').replace('br.', 'br_');
38
49
 
39
50
  if (inst[0] === Opcodes.if || inst[0] === Opcodes.loop || inst[0] === Opcodes.block || inst[0] === Opcodes.else || inst[0] === Opcodes.try || inst[0] === Opcodes.catch_all) depth++;
40
51
 
@@ -45,6 +56,11 @@ export default (wasm, name = '', ind = 0, locals = {}, params = [], returns = []
45
56
  } else if (inst[0] === Opcodes.i32_load || inst[0] === Opcodes.i64_load || inst[0] === Opcodes.f64_load || inst[0] === Opcodes.i32_store || inst[0] === Opcodes.i64_store || inst[0] === Opcodes.f64_store || inst[0] === Opcodes.i32_store16 || inst[0] === Opcodes.i32_load16_u) {
46
57
  out += ` ${inst[1]} ${read_unsignedLEB128(inst.slice(2))}`;
47
58
  } else for (const operand of inst.slice(1)) {
59
+ if (typeof operand === 'string') {
60
+ out += ` ;; ${operand}`;
61
+ continue;
62
+ }
63
+
48
64
  if (inst[0] === Opcodes.if || inst[0] === Opcodes.loop || inst[0] === Opcodes.block) {
49
65
  if (operand === Blocktype.void) continue;
50
66
  out += ` ${invValtype[operand]}`;
@@ -57,7 +73,7 @@ export default (wasm, name = '', ind = 0, locals = {}, params = [], returns = []
57
73
  out += ` ;; label @${depth}`;
58
74
  }
59
75
 
60
- if (inst[0] === Opcodes.br) {
76
+ if (inst[0] === Opcodes.br || inst[0] === Opcodes.br_if) {
61
77
  out += ` ;; goto @${depth - inst[1]}`;
62
78
  }
63
79
 
@@ -9,11 +9,15 @@ export const number = (n, valtype = valtypeBinary) => {
9
9
  }
10
10
  };
11
11
 
12
- const enforceTwoBytes = arr => [ arr[0] ?? 0, arr[1] ?? 0, arr[2] ?? 0, arr[3] ?? 0 ];
12
+ export const enforceOneByte = arr => [ arr[0] ?? 0 ];
13
+ export const enforceTwoBytes = arr => [ arr[0] ?? 0, arr[1] ?? 0 ];
14
+ export const enforceFourBytes = arr => [ arr[0] ?? 0, arr[1] ?? 0, arr[2] ?? 0, arr[3] ?? 0 ];
15
+ 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 ];
16
+
13
17
  export const i32x4 = (a, b, c, d) => [ [
14
18
  ...Opcodes.v128_const,
15
- ...enforceTwoBytes(signedLEB128(a)),
16
- ...enforceTwoBytes(signedLEB128(b)),
17
- ...enforceTwoBytes(signedLEB128(c)),
18
- ...enforceTwoBytes(signedLEB128(d))
19
+ ...enforceFourBytes(signedLEB128(a)),
20
+ ...enforceFourBytes(signedLEB128(b)),
21
+ ...enforceFourBytes(signedLEB128(c)),
22
+ ...enforceFourBytes(signedLEB128(d))
19
23
  ] ];
package/compiler/index.js CHANGED
@@ -4,6 +4,8 @@ import opt from './opt.js';
4
4
  import produceSections from './sections.js';
5
5
  import decompile from './decompile.js';
6
6
  import { BuiltinPreludes } from './builtins.js';
7
+ import toc from './2c.js';
8
+
7
9
 
8
10
  globalThis.decompile = decompile;
9
11
 
@@ -15,7 +17,8 @@ const areaColors = {
15
17
  codegen: [ 20, 80, 250 ],
16
18
  opt: [ 250, 20, 80 ],
17
19
  sections: [ 20, 250, 80 ],
18
- alloc: [ 250, 250, 20 ]
20
+ alloc: [ 250, 250, 20 ],
21
+ '2c': [ 20, 250, 250 ]
19
22
  };
20
23
 
21
24
  globalThis.log = (area, ...args) => console.log(`\u001b[90m[\u001b[0m${rgb(...areaColors[area], area)}\u001b[90m]\u001b[0m`, ...args);
@@ -36,10 +39,16 @@ const logFuncs = (funcs, globals, exceptions) => {
36
39
  console.log();
37
40
  };
38
41
 
42
+ const getArg = name => process.argv.find(x => x.startsWith(`-${name}=`))?.slice(name.length + 2);
43
+
44
+ const writeFileSync = (typeof process !== 'undefined' ? (await import('node:fs')).writeFileSync : undefined);
45
+ const execSync = (typeof process !== 'undefined' ? (await import('node:child_process')).execSync : undefined);
46
+
39
47
  export default (code, flags) => {
40
48
  globalThis.optLog = process.argv.includes('-opt-log');
41
49
  globalThis.codeLog = process.argv.includes('-code-log');
42
50
  globalThis.allocLog = process.argv.includes('-alloc-log');
51
+ globalThis.regexLog = process.argv.includes('-regex-log');
43
52
 
44
53
  for (const x in BuiltinPreludes) {
45
54
  if (code.indexOf(x + '(') !== -1) code = BuiltinPreludes[x] + code;
@@ -50,27 +59,60 @@ export default (code, flags) => {
50
59
  if (flags.includes('info')) console.log(`1. parsed in ${(performance.now() - t0).toFixed(2)}ms`);
51
60
 
52
61
  const t1 = performance.now();
53
- const { funcs, globals, tags, exceptions, pages } = codeGen(program);
62
+ const { funcs, globals, tags, exceptions, pages, data } = codeGen(program);
54
63
  if (flags.includes('info')) console.log(`2. generated code in ${(performance.now() - t1).toFixed(2)}ms`);
55
64
 
56
65
  if (process.argv.includes('-funcs')) logFuncs(funcs, globals, exceptions);
57
66
 
58
67
  const t2 = performance.now();
59
- opt(funcs, globals);
68
+ opt(funcs, globals, pages);
60
69
  if (flags.includes('info')) console.log(`3. optimized code in ${(performance.now() - t2).toFixed(2)}ms`);
61
70
 
62
71
  if (process.argv.includes('-opt-funcs')) logFuncs(funcs, globals, exceptions);
63
72
 
64
73
  const t3 = performance.now();
65
- const sections = produceSections(funcs, globals, tags, pages, flags);
74
+ const sections = produceSections(funcs, globals, tags, pages, data, flags);
66
75
  if (flags.includes('info')) console.log(`4. produced sections in ${(performance.now() - t3).toFixed(2)}ms`);
67
76
 
68
77
  if (allocLog) {
69
78
  const wasmPages = Math.ceil((pages.size * pageSize) / 65536);
70
79
  const bytes = wasmPages * 65536;
71
80
  log('alloc', `\x1B[1mallocated ${bytes / 1024}KiB\x1B[0m for ${pages.size} things using ${wasmPages} Wasm page${wasmPages === 1 ? '' : 's'}`);
72
- // console.log([...pages.keys()].map(x => `\x1B[36m - ${x}\x1B[0m`).join('\n'));
81
+ console.log([...pages.keys()].map(x => `\x1B[36m - ${x}\x1B[0m`).join('\n') + '\n');
82
+ }
83
+
84
+ const out = { wasm: sections, funcs, globals, tags, exceptions, pages };
85
+
86
+ const target = getArg('target') ?? getArg('t') ?? 'wasm';
87
+ const outFile = getArg('o');
88
+
89
+ if (target === 'c') {
90
+ const c = toc(out);
91
+
92
+ if (outFile) {
93
+ writeFileSync(outFile, c);
94
+ } else {
95
+ console.log(c);
96
+ }
97
+
98
+ process.exit();
99
+ }
100
+
101
+ if (target === 'native') {
102
+ const compiler = getArg('compiler') ?? 'clang';
103
+ const cO = getArg('cO') ?? 'Ofast';
104
+
105
+ const tmpfile = 'tmp.c';
106
+ const args = [ compiler, tmpfile, '-o', outFile ?? (process.platform === 'win32' ? 'out.exe' : 'out'), '-' + cO, '-march=native' ];
107
+
108
+ const c = toc(out);
109
+ writeFileSync(tmpfile, c);
110
+
111
+ // obvious command escape is obvious
112
+ execSync(args.join(' '), { stdio: 'inherit' });
113
+
114
+ process.exit();
73
115
  }
74
116
 
75
- return { wasm: sections, funcs, globals, tags, exceptions, pages };
117
+ return out;
76
118
  };