Skip to content

Commit

Permalink
Rewrite: v0.2
Browse files Browse the repository at this point in the history
MASSIVE rewrite! Now featuring runtime typechecker, pluggable parser, and many many fixes/refactors/tweaks.

test262: 11.12% (+0.02) | πŸ§ͺ 49377 (+534) | 🀠 5492 (+68) | ❌ 1258 (+152) | πŸ’€ 8345 (-685) | 🧩 1726 (+1454) | πŸ’₯ 4378 (+196) | ⏰ 1 | πŸ“ 28177 (-651)
  • Loading branch information
CanadaHonk committed Jan 22, 2024
1 parent afb21d1 commit 77e30e8
Show file tree
Hide file tree
Showing 22 changed files with 1,532 additions and 950 deletions.
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ sw.js
logo.png
index.html
CNAME
publish.js

# tmp
/asur
Expand Down
57 changes: 40 additions & 17 deletions compiler/2c.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { read_ieee754_binary64, read_signedLEB128 } from './encoding.js';
import { Blocktype, Opcodes, Valtype } from './wasmSpec.js';
import { operatorOpcode } from './expression.js';
import { log } from "./log.js";

const CValtype = {
i8: 'char',
Expand Down Expand Up @@ -45,20 +46,31 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
}, {});
const invGlobals = inv(globals, x => x.idx);

const sanitize = str => str.replace(/[^0-9a-zA-Z_]/g, _ => String.fromCharCode(97 + _.charCodeAt(0) % 32));

for (const x in invGlobals) {
invGlobals[x] = sanitize(invGlobals[x]);
}

const includes = new Map(), unixIncludes = new Map(), winIncludes = new Map();
let out = '';

// TODO: make type i16
let out = `struct ReturnValue {
${CValtype.f64} value;
${CValtype.i32} type;
};\n\n`;

for (const x in globals) {
const g = globals[x];

out += `${CValtype[g.type]} ${x} = ${g.init ?? 0}`;
out += `${CValtype[g.type]} ${sanitize(x)} = ${g.init ?? 0}`;
out += ';\n';
}

for (const [ x, p ] of pages) {
out += `${CValtype[p.type]} ${x.replace(': ', '_').replace(/[^0-9a-zA-Z_]/g, '')}[100]`;
out += ';\n';
}
// for (const [ x, p ] of pages) {
// out += `${CValtype[p.type]} ${x.replace(': ', '_').replace(/[^0-9a-zA-Z_]/g, '')}[100]`;
// out += ';\n';
// }

if (out) out += '\n';

Expand Down Expand Up @@ -100,19 +112,21 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
depth = 1;

const invLocals = inv(f.locals, x => x.idx);
if (f.returns.length > 1) todo('funcs returning >1 value unsupported');
// if (f.returns.length > 1) todo('funcs returning >1 value unsupported');

const sanitize = str => str.replace(/[^0-9a-zA-Z_]/g, _ => String.fromCharCode(97 + _.charCodeAt(0) % 32));
for (const x in invLocals) {
invLocals[x] = sanitize(invLocals[x]);
}

const returns = f.returns.length === 1;
const returns = f.returns.length > 0;

const shouldInline = f.internal;
out += `${f.name === 'main' ? 'int' : CValtype[f.returns[0]]} ${shouldInline ? 'inline ' : ''}${sanitize(f.name)}(${f.params.map((x, i) => `${CValtype[x]} ${invLocals[i]}`).join(', ')}) {\n`;
out += `${f.name === 'main' ? 'int' : (f.internal ? 'double' : 'struct ReturnValue')} ${shouldInline ? 'inline ' : ''}${sanitize(f.name)}(${f.params.map((x, i) => `${CValtype[x]} ${invLocals[i]}`).join(', ')}) {\n`;

const localKeys = Object.keys(f.locals).sort((a, b) => f.locals[a].idx - f.locals[b].idx).slice(f.params.length).sort((a, b) => f.locals[a].idx - f.locals[b].idx);
for (const x of localKeys) {
const l = f.locals[x];
line(`${CValtype[l.type]} ${x} = 0`);
line(`${CValtype[l.type]} ${sanitize(x)} = 0`);
}

if (localKeys.length !== 0) out += '\n';
Expand Down Expand Up @@ -202,7 +216,8 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
break;

case Opcodes.return:
line(`return${returns ? ` ${removeBrackets(vals.pop())}` : ''}`);
// line(`return${returns ? ` ${removeBrackets(vals.pop())}` : ''}`);
line(`return${returns ? ` (struct ReturnValue){ ${removeBrackets(vals.pop())}, ${removeBrackets(vals.pop())} }` : ''}`);
break;

case Opcodes.if:
Expand Down Expand Up @@ -304,7 +319,7 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
break;

default:
log('2c', `unimplemented import: ${importFunc.name}`);
log.warning('2c', `unimplemented import: ${importFunc.name}`);
break;
}

Expand All @@ -314,13 +329,21 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
let args = [];
for (let j = 0; j < func.params.length; j++) args.unshift(removeBrackets(vals.pop()));

if (func.returns.length === 1) vals.push(`${sanitize(func.name)}(${args.join(', ')})`)
else line(`${sanitize(func.name)}(${args.join(', ')})`);
if (func.returns.length > 0) {
if (func.internal) {
vals.push(`${sanitize(func.name)}(${args.join(', ')})`);
} else {
line(`const struct ReturnValue _ = ${sanitize(func.name)}(${args.join(', ')})`);
vals.push(`_.value`);
vals.push(`_.type`);
}
} else line(`${sanitize(func.name)}(${args.join(', ')})`);

break;

case Opcodes.drop:
line(vals.pop());
// line(vals.pop());
vals.pop();
break;

case Opcodes.br:
Expand All @@ -330,7 +353,7 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
break;

default:
log('2c', `unimplemented op: ${invOpcodes[i[0]]}`);
log.warning('2c', `unimplemented op: ${invOpcodes[i[0]]}`);
// todo(`unimplemented op: ${invOpcodes[i[0]]}`);
}

Expand Down
28 changes: 16 additions & 12 deletions compiler/builtins.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ export const importedFuncs = [
params: 1,
returns: 0
},
{
name: 'assert',
import: 'a',
params: 1,
returns: 0
},
{
name: 'time',
import: 't',
Expand Down Expand Up @@ -401,7 +395,7 @@ export const BuiltinFuncs = function() {

// this is an implementation of xorshift128+ (in wasm bytecode)
// fun fact: v8, SM, JSC also use this (you will need this fun fact to maintain your sanity reading this code)
const prngSeed0 = Math.floor(Math.random() * (2 ** 30)), prngSeed1 = Math.floor(Math.random() * (2 ** 30));
const prngSeed0 = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER), prngSeed1 = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);

this.__Math_random = {
floatOnly: true,
Expand Down Expand Up @@ -460,15 +454,25 @@ export const BuiltinFuncs = function() {
// it feels like it but it breaks values

// | 0x3FF0000000000000
[ Opcodes.i64_const, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf8, 0x3f ],
[ Opcodes.i64_or ],
// [ Opcodes.i64_const, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf8, 0x3f ],
// [ Opcodes.i64_or ],

// bit cast as f64
[ Opcodes.f64_reinterpret_i64 ],
// [ Opcodes.f64_reinterpret_i64 ],

// - 1
...number(1),
[ Opcodes.f64_sub ],
// ...number(1),
// [ Opcodes.f64_sub ],

...number((1 << 53) - 1, Valtype.i64),
[ Opcodes.i64_and ],

// double(mantissa)
[ Opcodes.f64_convert_i64_u ],

// / (1 << 53)
...number(1 << 53),
[ Opcodes.f64_div ]
]
};

Expand Down
Loading

0 comments on commit 77e30e8

Please sign in to comment.