porffor 0.14.0-4e46400a9 → 0.14.0-a24ac8cf2

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.
@@ -65,6 +65,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
65
65
  importFuncs = [...imports.values()];
66
66
 
67
67
  // fix call indexes for non-imports
68
+ // also fix call_indirect types
68
69
  const delta = importedFuncs.length - importFuncs.length;
69
70
  for (const f of funcs) {
70
71
  f.originalIndex = f.index;
@@ -74,6 +75,16 @@ export default (funcs, globals, tags, pages, data, flags) => {
74
75
  if ((inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) && inst[1] >= importedFuncs.length) {
75
76
  inst[1] -= delta;
76
77
  }
78
+
79
+ if (inst[0] === Opcodes.call_indirect) {
80
+ const params = [];
81
+ for (let i = 0; i < inst[1]; i++) {
82
+ params.push(valtypeBinary, Valtype.i32);
83
+ }
84
+
85
+ const returns = [ valtypeBinary, Valtype.i32 ];
86
+ inst[1] = getType(params, returns);
87
+ }
77
88
  }
78
89
  }
79
90
  }
@@ -101,7 +112,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
101
112
  encodeVector([ [
102
113
  0x00,
103
114
  Opcodes.i32_const, 0, Opcodes.end,
104
- encodeVector(funcs.map(x => x.index))
115
+ ...encodeVector(funcs.map(x => x.index))
105
116
  ] ])
106
117
  );
107
118
 
@@ -351,9 +351,7 @@ const generateReturn = (scope, decl) => {
351
351
 
352
352
  return [
353
353
  ...generate(scope, decl.argument),
354
- ...(scope.returnType != null ? [] : [
355
- ...getNodeType(scope, decl.argument)
356
- ]),
354
+ ...(scope.returnType != null ? [] : getNodeType(scope, decl.argument)),
357
355
  [ Opcodes.return ]
358
356
  ];
359
357
  };
@@ -1451,6 +1449,10 @@ const countLeftover = wasm => {
1451
1449
  } else count--;
1452
1450
  if (func) count += func.returns.length;
1453
1451
  }
1452
+ } else if (inst[0] === Opcodes.call_indirect) {
1453
+ count--; // funcidx
1454
+ count -= inst[1] * 2; // params * 2 (typed)
1455
+ count += 2; // fixed return (value, type)
1454
1456
  } else count--;
1455
1457
 
1456
1458
  // console.log(count, decompile([ inst ]).slice(0, -1));
@@ -1833,22 +1835,44 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1833
1835
 
1834
1836
  if (idx === undefined) {
1835
1837
  if (scope.locals[name] !== undefined || globals[name] !== undefined || builtinVars[name] !== undefined) {
1836
- if (!Prefs.indirectCalls) return internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, true);
1837
-
1838
1838
  const [ local, global ] = lookupName(scope, name);
1839
- funcs.table = true;
1839
+ if (!Prefs.indirectCalls || local == null) return internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, true);
1840
1840
 
1841
1841
  // todo: only works when:
1842
1842
  // 1. arg count matches arg count of function
1843
1843
  // 2. function uses typedParams and typedReturns
1844
- return typeSwitch(scope, getNodeType(decl.callee), {
1844
+
1845
+ funcs.table = true;
1846
+
1847
+ let args = decl.arguments;
1848
+ let argWasm = [];
1849
+
1850
+ for (let i = 0; i < args.length; i++) {
1851
+ const arg = args[i];
1852
+ argWasm = argWasm.concat(generate(scope, arg));
1853
+
1854
+ if (valtypeBinary !== Valtype.i32 && (
1855
+ (builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32) ||
1856
+ (importedFuncs[name] && name.startsWith('profile'))
1857
+ )) {
1858
+ argWasm.push(Opcodes.i32_to);
1859
+ }
1860
+
1861
+ argWasm = argWasm.concat(getNodeType(scope, arg));
1862
+ }
1863
+
1864
+ return typeSwitch(scope, getNodeType(scope, decl.callee), {
1845
1865
  [TYPES.function]: [
1866
+ ...argWasm,
1846
1867
  [ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
1847
- [ Opcodes.call_indirect ]
1868
+ Opcodes.i32_to_u,
1869
+ [ Opcodes.call_indirect, args.length, 0 ],
1870
+ ...setLastType(scope)
1848
1871
  ],
1849
1872
  default: internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, true)
1850
1873
  });
1851
1874
  }
1875
+
1852
1876
  return internalThrow(scope, 'ReferenceError', `${unhackName(name)} is not defined`, true);
1853
1877
  }
1854
1878
 
@@ -3628,8 +3652,10 @@ const internalConstrs = {
3628
3652
  }),
3629
3653
 
3630
3654
  // print space
3631
- ...number(32),
3632
- [ Opcodes.call, importedFuncs.printChar ]
3655
+ ...(i !== decl.arguments.length - 1 ? [
3656
+ ...number(32),
3657
+ [ Opcodes.call, importedFuncs.printChar ]
3658
+ ] : [])
3633
3659
  );
3634
3660
  }
3635
3661
 
@@ -3639,6 +3665,8 @@ const internalConstrs = {
3639
3665
  [ Opcodes.call, importedFuncs.printChar ]
3640
3666
  );
3641
3667
 
3668
+ out.push(...number(UNDEFINED));
3669
+
3642
3670
  return out;
3643
3671
  },
3644
3672
  type: TYPES.undefined,
package/compiler/index.js CHANGED
@@ -12,14 +12,7 @@ globalThis.decompile = decompile;
12
12
  const logFuncs = (funcs, globals, exceptions) => {
13
13
  console.log('\n' + underline(bold('funcs')));
14
14
 
15
- const startIndex = funcs.sort((a, b) => a.index - b.index)[0].index;
16
15
  for (const f of funcs) {
17
- console.log(`${underline(f.name)} (${f.index - startIndex})`);
18
-
19
- console.log(`params: ${f.params.map((_, i) => Object.keys(f.locals)[Object.values(f.locals).indexOf(Object.values(f.locals).find(x => x.idx === i))]).join(', ')}`);
20
- console.log(`returns: ${f.returns.length > 0 ? true : false}`);
21
- console.log(`locals: ${Object.keys(f.locals).sort((a, b) => f.locals[a].idx - f.locals[b].idx).map(x => `${x} (${f.locals[x].idx})`).join(', ')}`);
22
- console.log();
23
16
  console.log(decompile(f.wasm, f.name, f.index, f.locals, f.params, f.returns, funcs, globals, exceptions));
24
17
  }
25
18
 
@@ -44,12 +37,14 @@ export default (code, flags) => {
44
37
  opt(funcs, globals, pages, tags, exceptions);
45
38
  if (Prefs.profileCompiler) console.log(`3. optimized in ${(performance.now() - t2).toFixed(2)}ms`);
46
39
 
47
- if (Prefs.optFuncs) logFuncs(funcs, globals, exceptions);
40
+ // if (Prefs.optFuncs) logFuncs(funcs, globals, exceptions);
48
41
 
49
42
  const t3 = performance.now();
50
43
  const wasm = assemble(funcs, globals, tags, pages, data, flags);
51
44
  if (Prefs.profileCompiler) console.log(`4. assembled in ${(performance.now() - t3).toFixed(2)}ms`);
52
45
 
46
+ if (Prefs.optFuncs) logFuncs(funcs, globals, exceptions);
47
+
53
48
  if (Prefs.allocLog) {
54
49
  const wasmPages = Math.ceil((pages.size * pageSize) / 65536);
55
50
  const bytes = wasmPages * 65536;
@@ -18,7 +18,7 @@ const compile = async (file, [ _funcs, _globals ]) => {
18
18
  first = source.slice(0, source.indexOf('\n'));
19
19
  }
20
20
 
21
- let args = ['--bytestring', '--todo-time=compile', '--no-aot-pointer-opt', '--no-treeshake-wasm-imports', '--no-rm-unused-types', '--scoped-page-names', '--funsafe-no-unlikely-proto-checks', '--parse-types', '--opt-types'];
21
+ let args = ['--bytestring', '--todo-time=compile', '--no-aot-pointer-opt', '--no-indirect-calls', '--no-treeshake-wasm-imports', '--no-rm-unused-types', '--scoped-page-names', '--funsafe-no-unlikely-proto-checks', '--parse-types', '--opt-types'];
22
22
  if (first.startsWith('// @porf')) {
23
23
  args = args.concat(first.slice('// @porf '.length).split(' '));
24
24
  }
package/compiler/prefs.js CHANGED
@@ -1,4 +1,4 @@
1
- const onByDefault = [ 'bytestring', 'aotPointerOpt', 'treeshakeWasmImports', 'alwaysMemory' ];
1
+ const onByDefault = [ 'bytestring', 'aotPointerOpt', 'treeshakeWasmImports', 'alwaysMemory', 'indirectCalls' ];
2
2
 
3
3
  let cache = {};
4
4
  const obj = new Proxy({}, {
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.14.0-4e46400a9",
4
+ "version": "0.14.0-a24ac8cf2",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "scripts": {