porffor 0.1.1 → 0.2.0-c6c8c81
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.
- package/README.md +184 -204
- package/compiler/2c.js +377 -0
- package/compiler/builtins/base64.js +91 -91
- package/compiler/builtins.js +19 -13
- package/compiler/codeGen.js +1313 -418
- package/compiler/decompile.js +35 -9
- package/compiler/embedding.js +9 -5
- package/compiler/encoding.js +8 -2
- package/compiler/index.js +55 -17
- package/compiler/log.js +15 -0
- package/compiler/opt.js +357 -258
- package/compiler/parse.js +24 -1
- package/compiler/prototype.js +263 -56
- package/compiler/sections.js +51 -8
- package/compiler/wasmSpec.js +3 -0
- package/compiler/wrap.js +20 -6
- package/package.json +6 -1
- package/porf.cmd +1 -1
- package/rhemyn/README.md +37 -0
- package/rhemyn/compile.js +214 -0
- package/rhemyn/parse.js +321 -0
- package/rhemyn/test/parse.js +59 -0
- package/runner/index.js +54 -31
- package/runner/info.js +37 -2
- package/runner/profile.js +1 -2
- package/runner/repl.js +13 -11
- package/runner/results.json +1 -0
- package/runner/transform.js +15 -36
- package/runner/version.js +10 -0
- package/CNAME +0 -1
- package/index.html +0 -1264
- package/logo.png +0 -0
- package/sw.js +0 -26
package/compiler/2c.js
ADDED
@@ -0,0 +1,377 @@
|
|
1
|
+
import { read_ieee754_binary64, read_signedLEB128 } from './encoding.js';
|
2
|
+
import { Blocktype, Opcodes, Valtype } from './wasmSpec.js';
|
3
|
+
import { operatorOpcode } from './expression.js';
|
4
|
+
import { log } from "./log.js";
|
5
|
+
|
6
|
+
const CValtype = {
|
7
|
+
i8: 'char',
|
8
|
+
i16: 'unsigned short', // presume all i16 stuff is unsigned
|
9
|
+
i32: 'long',
|
10
|
+
i32_u: 'unsigned long',
|
11
|
+
i64: 'long long',
|
12
|
+
i64_u: 'unsigned long long',
|
13
|
+
|
14
|
+
f32: 'float',
|
15
|
+
f64: 'double',
|
16
|
+
|
17
|
+
undefined: 'void'
|
18
|
+
};
|
19
|
+
|
20
|
+
const inv = (obj, keyMap = x => x) => Object.keys(obj).reduce((acc, x) => { acc[keyMap(obj[x])] = x; return acc; }, {});
|
21
|
+
const invOpcodes = inv(Opcodes);
|
22
|
+
|
23
|
+
for (const x in CValtype) {
|
24
|
+
if (Valtype[x]) CValtype[Valtype[x]] = CValtype[x];
|
25
|
+
}
|
26
|
+
|
27
|
+
const todo = msg => {
|
28
|
+
class TodoError extends Error {
|
29
|
+
constructor(message) {
|
30
|
+
super(message);
|
31
|
+
this.name = 'TodoError';
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
throw new TodoError(`todo: ${msg}`);
|
36
|
+
};
|
37
|
+
|
38
|
+
const removeBrackets = str => str.startsWith('(') && str.endsWith(')') ? str.slice(1, -1) : str;
|
39
|
+
|
40
|
+
export default ({ funcs, globals, tags, exceptions, pages }) => {
|
41
|
+
const invOperatorOpcode = Object.values(operatorOpcode).reduce((acc, x) => {
|
42
|
+
for (const k in x) {
|
43
|
+
acc[x[k]] = k;
|
44
|
+
}
|
45
|
+
return acc;
|
46
|
+
}, {});
|
47
|
+
const invGlobals = inv(globals, x => x.idx);
|
48
|
+
|
49
|
+
const sanitize = str => str.replace(/[^0-9a-zA-Z_]/g, _ => String.fromCharCode(97 + _.charCodeAt(0) % 32));
|
50
|
+
|
51
|
+
for (const x in invGlobals) {
|
52
|
+
invGlobals[x] = sanitize(invGlobals[x]);
|
53
|
+
}
|
54
|
+
|
55
|
+
const includes = new Map(), unixIncludes = new Map(), winIncludes = new Map();
|
56
|
+
|
57
|
+
// TODO: make type i16
|
58
|
+
let out = `struct ReturnValue {
|
59
|
+
${CValtype.f64} value;
|
60
|
+
${CValtype.i32} type;
|
61
|
+
};\n\n`;
|
62
|
+
|
63
|
+
for (const x in globals) {
|
64
|
+
const g = globals[x];
|
65
|
+
|
66
|
+
out += `${CValtype[g.type]} ${sanitize(x)} = ${g.init ?? 0}`;
|
67
|
+
out += ';\n';
|
68
|
+
}
|
69
|
+
|
70
|
+
// for (const [ x, p ] of pages) {
|
71
|
+
// out += `${CValtype[p.type]} ${x.replace(': ', '_').replace(/[^0-9a-zA-Z_]/g, '')}[100]`;
|
72
|
+
// out += ';\n';
|
73
|
+
// }
|
74
|
+
|
75
|
+
if (out) out += '\n';
|
76
|
+
|
77
|
+
let depth = 1;
|
78
|
+
const line = (str, semi = true) => out += `${' '.repeat(depth * 2)}${str}${semi ? ';' : ''}\n`;
|
79
|
+
const lines = lines => {
|
80
|
+
for (const x of lines) {
|
81
|
+
out += `${' '.repeat(depth * 2)}${x}\n`;
|
82
|
+
}
|
83
|
+
};
|
84
|
+
|
85
|
+
const platformSpecific = (win, unix, add = true) => {
|
86
|
+
let tmp = '';
|
87
|
+
|
88
|
+
if (win) {
|
89
|
+
if (add) out += '#ifdef _WIN32\n';
|
90
|
+
else tmp += '#ifdef _WIN32\n';
|
91
|
+
|
92
|
+
if (add) lines(win.split('\n'));
|
93
|
+
else tmp += win + (win.endsWith('\n') ? '' : '\n');
|
94
|
+
}
|
95
|
+
|
96
|
+
if (unix) {
|
97
|
+
if (add) out += (win ? '#else' : '#ifndef _WIN32') + '\n';
|
98
|
+
else tmp += (win ? '#else' : '#ifndef _WIN32') + '\n';
|
99
|
+
|
100
|
+
if (add) lines(unix.split('\n'));
|
101
|
+
else tmp += unix + (unix.endsWith('\n') ? '' : '\n');
|
102
|
+
}
|
103
|
+
|
104
|
+
if (win || unix)
|
105
|
+
if (add) out += '#endif\n';
|
106
|
+
else tmp += '#endif\n';
|
107
|
+
|
108
|
+
return tmp;
|
109
|
+
};
|
110
|
+
|
111
|
+
for (const f of funcs) {
|
112
|
+
depth = 1;
|
113
|
+
|
114
|
+
const invLocals = inv(f.locals, x => x.idx);
|
115
|
+
// if (f.returns.length > 1) todo('funcs returning >1 value unsupported');
|
116
|
+
|
117
|
+
for (const x in invLocals) {
|
118
|
+
invLocals[x] = sanitize(invLocals[x]);
|
119
|
+
}
|
120
|
+
|
121
|
+
const returns = f.returns.length > 0;
|
122
|
+
|
123
|
+
const shouldInline = f.internal;
|
124
|
+
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`;
|
125
|
+
|
126
|
+
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);
|
127
|
+
for (const x of localKeys) {
|
128
|
+
const l = f.locals[x];
|
129
|
+
line(`${CValtype[l.type]} ${sanitize(x)} = 0`);
|
130
|
+
}
|
131
|
+
|
132
|
+
if (localKeys.length !== 0) out += '\n';
|
133
|
+
|
134
|
+
let vals = [];
|
135
|
+
const endNeedsCurly = [], ignoreEnd = [];
|
136
|
+
let beginLoop = false, lastCond = false, ifTernary = false;
|
137
|
+
for (let _ = 0; _ < f.wasm.length; _++) {
|
138
|
+
const i = f.wasm[_];
|
139
|
+
|
140
|
+
if (invOperatorOpcode[i[0]]) {
|
141
|
+
const b = vals.pop();
|
142
|
+
const a = vals.pop();
|
143
|
+
|
144
|
+
let op = invOperatorOpcode[i[0]];
|
145
|
+
if (op.length === 3) op = op.slice(0, 2);
|
146
|
+
|
147
|
+
if (['==', '!=', '>', '>=', '<', '<='].includes(op)) lastCond = true;
|
148
|
+
else lastCond = false;
|
149
|
+
|
150
|
+
// vals.push(`(${removeBrackets(a)} ${op} ${b})`);
|
151
|
+
vals.push(`(${a} ${op} ${b})`);
|
152
|
+
continue;
|
153
|
+
}
|
154
|
+
|
155
|
+
// misc insts
|
156
|
+
if (i[0] === 0xfc) {
|
157
|
+
switch (i[1]) {
|
158
|
+
// i32_trunc_sat_f64_s
|
159
|
+
case 0x02:
|
160
|
+
vals.push(`(${CValtype.i32})${vals.pop()}`);
|
161
|
+
break;
|
162
|
+
|
163
|
+
// i32_trunc_sat_f64_u
|
164
|
+
case 0x03:
|
165
|
+
vals.push(`(${CValtype.i32})(${CValtype.i32_u})${vals.pop()}`);
|
166
|
+
break;
|
167
|
+
}
|
168
|
+
|
169
|
+
lastCond = false;
|
170
|
+
continue;
|
171
|
+
}
|
172
|
+
|
173
|
+
switch (i[0]) {
|
174
|
+
case Opcodes.i32_const:
|
175
|
+
case Opcodes.i64_const:
|
176
|
+
vals.push(read_signedLEB128(i.slice(1)).toString());
|
177
|
+
break;
|
178
|
+
|
179
|
+
case Opcodes.f64_const:
|
180
|
+
vals.push(read_ieee754_binary64(i.slice(1)).toExponential());
|
181
|
+
break;
|
182
|
+
|
183
|
+
case Opcodes.local_get:
|
184
|
+
vals.push(`${invLocals[i[1]]}`);
|
185
|
+
break;
|
186
|
+
|
187
|
+
case Opcodes.local_set:
|
188
|
+
line(`${invLocals[i[1]]} = ${removeBrackets(vals.pop())}`);
|
189
|
+
break;
|
190
|
+
|
191
|
+
case Opcodes.local_tee:
|
192
|
+
// line(`${invLocals[i[1]]} = ${removeBrackets(vals.pop())}`);
|
193
|
+
// vals.push(`${invLocals[i[1]]}`);
|
194
|
+
vals.push(`((${invLocals[i[1]]} = ${vals.pop()}))`);
|
195
|
+
break;
|
196
|
+
|
197
|
+
case Opcodes.global_get:
|
198
|
+
vals.push(`${invGlobals[i[1]]}`);
|
199
|
+
break;
|
200
|
+
|
201
|
+
case Opcodes.global_set:
|
202
|
+
line(`${invGlobals[i[1]]} = ${removeBrackets(vals.pop())}`);
|
203
|
+
break;
|
204
|
+
|
205
|
+
case Opcodes.f64_trunc:
|
206
|
+
// vals.push(`trunc(${vals.pop()})`);
|
207
|
+
vals.push(`(int)(${removeBrackets(vals.pop())})`); // this is ~10x faster with clang??
|
208
|
+
break;
|
209
|
+
|
210
|
+
case Opcodes.f64_convert_i32_u:
|
211
|
+
case Opcodes.f64_convert_i32_s:
|
212
|
+
case Opcodes.f64_convert_i64_u:
|
213
|
+
case Opcodes.f64_convert_i64_s:
|
214
|
+
// int to double
|
215
|
+
vals.push(`(double)${vals.pop()}`);
|
216
|
+
break;
|
217
|
+
|
218
|
+
case Opcodes.return:
|
219
|
+
// line(`return${returns ? ` ${removeBrackets(vals.pop())}` : ''}`);
|
220
|
+
line(`return${returns ? ` (struct ReturnValue){ ${removeBrackets(vals.pop())}, ${removeBrackets(vals.pop())} }` : ''}`);
|
221
|
+
break;
|
222
|
+
|
223
|
+
case Opcodes.if:
|
224
|
+
let cond = removeBrackets(vals.pop());
|
225
|
+
if (!lastCond) {
|
226
|
+
if (cond.startsWith('(long)')) cond = `${cond.slice(6)} == 1e+0`;
|
227
|
+
else cond += ' == 1';
|
228
|
+
}
|
229
|
+
|
230
|
+
ifTernary = i[1] !== Blocktype.void;
|
231
|
+
if (ifTernary) {
|
232
|
+
ifTernary = cond;
|
233
|
+
break;
|
234
|
+
}
|
235
|
+
|
236
|
+
if (beginLoop) {
|
237
|
+
beginLoop = false;
|
238
|
+
line(`while (${cond}) {`, false);
|
239
|
+
|
240
|
+
depth++;
|
241
|
+
endNeedsCurly.push(true);
|
242
|
+
ignoreEnd.push(false, true);
|
243
|
+
break;
|
244
|
+
}
|
245
|
+
|
246
|
+
line(`if (${cond}) {`, false);
|
247
|
+
|
248
|
+
depth++;
|
249
|
+
endNeedsCurly.push(true);
|
250
|
+
ignoreEnd.push(false);
|
251
|
+
break;
|
252
|
+
|
253
|
+
case Opcodes.else:
|
254
|
+
if (ifTernary) break;
|
255
|
+
|
256
|
+
depth--;
|
257
|
+
line(`} else {`, false);
|
258
|
+
depth++;
|
259
|
+
break;
|
260
|
+
|
261
|
+
case Opcodes.loop:
|
262
|
+
// not doing properly, fake a while loop
|
263
|
+
beginLoop = true;
|
264
|
+
break;
|
265
|
+
|
266
|
+
case Opcodes.end:
|
267
|
+
if (ignoreEnd.pop()) break;
|
268
|
+
|
269
|
+
if (ifTernary) {
|
270
|
+
const b = vals.pop();
|
271
|
+
const a = vals.pop();
|
272
|
+
vals.push(`${ifTernary} ? ${a} : ${b}`);
|
273
|
+
break;
|
274
|
+
}
|
275
|
+
|
276
|
+
depth--;
|
277
|
+
if (endNeedsCurly.pop() === true) line('}', false);
|
278
|
+
break;
|
279
|
+
|
280
|
+
case Opcodes.call:
|
281
|
+
let func = funcs.find(x => x.index === i[1]);
|
282
|
+
if (!func) {
|
283
|
+
const importFunc = importFuncs[i[1]];
|
284
|
+
switch (importFunc.name) {
|
285
|
+
case 'print':
|
286
|
+
line(`printf("%f\\n", ${vals.pop()})`);
|
287
|
+
includes.set('stdio.h', true);
|
288
|
+
break;
|
289
|
+
case 'printChar':
|
290
|
+
line(`printf("%c", (int)(${vals.pop()}))`);
|
291
|
+
includes.set('stdio.h', true);
|
292
|
+
break;
|
293
|
+
|
294
|
+
case 'time':
|
295
|
+
line(`double _time_out`);
|
296
|
+
/* platformSpecific(
|
297
|
+
`FILETIME _time_filetime;
|
298
|
+
GetSystemTimeAsFileTime(&_time_filetime);
|
299
|
+
|
300
|
+
ULARGE_INTEGER _time_ularge;
|
301
|
+
_time_ularge.LowPart = _time_filetime.dwLowDateTime;
|
302
|
+
_time_ularge.HighPart = _time_filetime.dwHighDateTime;
|
303
|
+
_time_out = (_time_ularge.QuadPart - 116444736000000000i64) / 10000.;`,
|
304
|
+
`struct timespec _time;
|
305
|
+
clock_gettime(CLOCK_MONOTONIC, &_time);
|
306
|
+
_time_out = _time.tv_nsec / 1000000.;`); */
|
307
|
+
platformSpecific(
|
308
|
+
`LARGE_INTEGER _time_freq, _time_t;
|
309
|
+
QueryPerformanceFrequency(&_time_freq);
|
310
|
+
QueryPerformanceCounter(&_time_t);
|
311
|
+
_time_out = ((double)_time_t.QuadPart / _time_freq.QuadPart) * 1000.;`,
|
312
|
+
`struct timespec _time;
|
313
|
+
clock_gettime(CLOCK_MONOTONIC, &_time);
|
314
|
+
_time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
315
|
+
vals.push(`_time_out`);
|
316
|
+
|
317
|
+
unixIncludes.set('time.h', true);
|
318
|
+
winIncludes.set('windows.h', true);
|
319
|
+
break;
|
320
|
+
|
321
|
+
default:
|
322
|
+
log.warning('2c', `unimplemented import: ${importFunc.name}`);
|
323
|
+
break;
|
324
|
+
}
|
325
|
+
|
326
|
+
break;
|
327
|
+
}
|
328
|
+
|
329
|
+
let args = [];
|
330
|
+
for (let j = 0; j < func.params.length; j++) args.unshift(removeBrackets(vals.pop()));
|
331
|
+
|
332
|
+
if (func.returns.length > 0) {
|
333
|
+
if (func.internal) {
|
334
|
+
vals.push(`${sanitize(func.name)}(${args.join(', ')})`);
|
335
|
+
} else {
|
336
|
+
line(`const struct ReturnValue _ = ${sanitize(func.name)}(${args.join(', ')})`);
|
337
|
+
vals.push(`_.value`);
|
338
|
+
vals.push(`_.type`);
|
339
|
+
}
|
340
|
+
} else line(`${sanitize(func.name)}(${args.join(', ')})`);
|
341
|
+
|
342
|
+
break;
|
343
|
+
|
344
|
+
case Opcodes.drop:
|
345
|
+
// line(vals.pop());
|
346
|
+
vals.pop();
|
347
|
+
break;
|
348
|
+
|
349
|
+
case Opcodes.br:
|
350
|
+
// ignore
|
351
|
+
// reset "stack"
|
352
|
+
vals = [];
|
353
|
+
break;
|
354
|
+
|
355
|
+
default:
|
356
|
+
log.warning('2c', `unimplemented op: ${invOpcodes[i[0]]}`);
|
357
|
+
// todo(`unimplemented op: ${invOpcodes[i[0]]}`);
|
358
|
+
}
|
359
|
+
|
360
|
+
lastCond = false;
|
361
|
+
}
|
362
|
+
|
363
|
+
if (vals.length === 1 && returns) {
|
364
|
+
line(`return ${vals.pop()}`);
|
365
|
+
}
|
366
|
+
|
367
|
+
out += '}\n\n';
|
368
|
+
}
|
369
|
+
|
370
|
+
depth = 0;
|
371
|
+
|
372
|
+
const makeIncludes = includes => [...includes.keys()].map(x => `#include <${x}>\n`).join('');
|
373
|
+
|
374
|
+
out = platformSpecific(makeIncludes(winIncludes), makeIncludes(unixIncludes), false) + '\n' + makeIncludes(includes) + '\n' + out;
|
375
|
+
|
376
|
+
return out;
|
377
|
+
};
|
@@ -1,92 +1,92 @@
|
|
1
|
-
var btoa_a = str => {
|
2
|
-
// todo: throw invalid character for unicode
|
3
|
-
|
4
|
-
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
5
|
-
const mask = (1 << 6) - 1;
|
6
|
-
|
7
|
-
let out = '';
|
8
|
-
let bits = 0, buffer = 0;
|
9
|
-
for (let i = 0; i < str.length; i++) {
|
10
|
-
buffer = (buffer << 8) | (0xff & str.charCodeAt(i));
|
11
|
-
bits += 8;
|
12
|
-
|
13
|
-
while (bits > 6) {
|
14
|
-
bits -= 6;
|
15
|
-
out += chars[mask & (buffer >> bits)];
|
16
|
-
}
|
17
|
-
}
|
18
|
-
|
19
|
-
if (bits) {
|
20
|
-
out += chars[mask & (buffer << (6 - bits))]
|
21
|
-
}
|
22
|
-
|
23
|
-
while ((out.length * 6) & 7) {
|
24
|
-
out += '=';
|
25
|
-
}
|
26
|
-
|
27
|
-
return out;
|
28
|
-
};
|
29
|
-
|
30
|
-
var btoa = function (input) {
|
31
|
-
// todo: throw invalid character for unicode
|
32
|
-
const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
33
|
-
|
34
|
-
let output = "";
|
35
|
-
let chr1, chr2, chr3, enc1, enc2, enc3, enc4;
|
36
|
-
let i = 0;
|
37
|
-
|
38
|
-
while (i < input.length) {
|
39
|
-
chr1 = input.charCodeAt(i++);
|
40
|
-
chr2 = input.charCodeAt(i++);
|
41
|
-
chr3 = input.charCodeAt(i++);
|
42
|
-
|
43
|
-
enc1 = chr1 >> 2;
|
44
|
-
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
45
|
-
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
46
|
-
enc4 = chr3 & 63;
|
47
|
-
|
48
|
-
if (isNaN(chr2)) {
|
49
|
-
enc3 = enc4 = 64;
|
50
|
-
} else if (isNaN(chr3)) {
|
51
|
-
enc4 = 64;
|
52
|
-
}
|
53
|
-
|
54
|
-
output += keyStr.charAt(enc1);
|
55
|
-
output += keyStr.charAt(enc2);
|
56
|
-
output += keyStr.charAt(enc3);
|
57
|
-
output += keyStr.charAt(enc4);
|
58
|
-
}
|
59
|
-
|
60
|
-
return output;
|
61
|
-
};
|
62
|
-
|
63
|
-
var atob_b = function (input) {
|
64
|
-
const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
65
|
-
|
66
|
-
let output = "";
|
67
|
-
let chr1, chr2, chr3;
|
68
|
-
let enc1, enc2, enc3, enc4;
|
69
|
-
let i = 0;
|
70
|
-
|
71
|
-
while (i < input.length) {
|
72
|
-
enc1 = keyStr.indexOf(input.charAt(i++));
|
73
|
-
enc2 = keyStr.indexOf(input.charAt(i++));
|
74
|
-
enc3 = keyStr.indexOf(input.charAt(i++));
|
75
|
-
enc4 = keyStr.indexOf(input.charAt(i++));
|
76
|
-
|
77
|
-
chr1 = (enc1 << 2) | (enc2 >> 4);
|
78
|
-
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
79
|
-
chr3 = ((enc3 & 3) << 6) | enc4;
|
80
|
-
|
81
|
-
output += String.fromCharCode(chr1);
|
82
|
-
|
83
|
-
if (enc3 != 64) {
|
84
|
-
output += String.fromCharCode(chr2);
|
85
|
-
}
|
86
|
-
if (enc4 != 64) {
|
87
|
-
output += String.fromCharCode(chr3);
|
88
|
-
}
|
89
|
-
}
|
90
|
-
|
91
|
-
return output;
|
1
|
+
var btoa_a = str => {
|
2
|
+
// todo: throw invalid character for unicode
|
3
|
+
|
4
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
5
|
+
const mask = (1 << 6) - 1;
|
6
|
+
|
7
|
+
let out = '';
|
8
|
+
let bits = 0, buffer = 0;
|
9
|
+
for (let i = 0; i < str.length; i++) {
|
10
|
+
buffer = (buffer << 8) | (0xff & str.charCodeAt(i));
|
11
|
+
bits += 8;
|
12
|
+
|
13
|
+
while (bits > 6) {
|
14
|
+
bits -= 6;
|
15
|
+
out += chars[mask & (buffer >> bits)];
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
if (bits) {
|
20
|
+
out += chars[mask & (buffer << (6 - bits))]
|
21
|
+
}
|
22
|
+
|
23
|
+
while ((out.length * 6) & 7) {
|
24
|
+
out += '=';
|
25
|
+
}
|
26
|
+
|
27
|
+
return out;
|
28
|
+
};
|
29
|
+
|
30
|
+
var btoa = function (input) {
|
31
|
+
// todo: throw invalid character for unicode
|
32
|
+
const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
33
|
+
|
34
|
+
let output = "";
|
35
|
+
let chr1, chr2, chr3, enc1, enc2, enc3, enc4;
|
36
|
+
let i = 0;
|
37
|
+
|
38
|
+
while (i < input.length) {
|
39
|
+
chr1 = input.charCodeAt(i++);
|
40
|
+
chr2 = input.charCodeAt(i++);
|
41
|
+
chr3 = input.charCodeAt(i++);
|
42
|
+
|
43
|
+
enc1 = chr1 >> 2;
|
44
|
+
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
45
|
+
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
46
|
+
enc4 = chr3 & 63;
|
47
|
+
|
48
|
+
if (isNaN(chr2)) {
|
49
|
+
enc3 = enc4 = 64;
|
50
|
+
} else if (isNaN(chr3)) {
|
51
|
+
enc4 = 64;
|
52
|
+
}
|
53
|
+
|
54
|
+
output += keyStr.charAt(enc1);
|
55
|
+
output += keyStr.charAt(enc2);
|
56
|
+
output += keyStr.charAt(enc3);
|
57
|
+
output += keyStr.charAt(enc4);
|
58
|
+
}
|
59
|
+
|
60
|
+
return output;
|
61
|
+
};
|
62
|
+
|
63
|
+
var atob_b = function (input) {
|
64
|
+
const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
65
|
+
|
66
|
+
let output = "";
|
67
|
+
let chr1, chr2, chr3;
|
68
|
+
let enc1, enc2, enc3, enc4;
|
69
|
+
let i = 0;
|
70
|
+
|
71
|
+
while (i < input.length) {
|
72
|
+
enc1 = keyStr.indexOf(input.charAt(i++));
|
73
|
+
enc2 = keyStr.indexOf(input.charAt(i++));
|
74
|
+
enc3 = keyStr.indexOf(input.charAt(i++));
|
75
|
+
enc4 = keyStr.indexOf(input.charAt(i++));
|
76
|
+
|
77
|
+
chr1 = (enc1 << 2) | (enc2 >> 4);
|
78
|
+
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
79
|
+
chr3 = ((enc3 & 3) << 6) | enc4;
|
80
|
+
|
81
|
+
output += String.fromCharCode(chr1);
|
82
|
+
|
83
|
+
if (enc3 != 64) {
|
84
|
+
output += String.fromCharCode(chr2);
|
85
|
+
}
|
86
|
+
if (enc4 != 64) {
|
87
|
+
output += String.fromCharCode(chr3);
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
return output;
|
92
92
|
};
|
package/compiler/builtins.js
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
import { Blocktype, Opcodes, Valtype } from "./wasmSpec.js";
|
2
2
|
import { number, i32x4 } from "./embedding.js";
|
3
|
-
import { signedLEB128 } from "./encoding.js";
|
4
3
|
|
5
4
|
export const importedFuncs = [
|
6
5
|
{
|
@@ -15,12 +14,6 @@ export const importedFuncs = [
|
|
15
14
|
params: 1,
|
16
15
|
returns: 0
|
17
16
|
},
|
18
|
-
{
|
19
|
-
name: 'assert',
|
20
|
-
import: 'a',
|
21
|
-
params: 1,
|
22
|
-
returns: 0
|
23
|
-
},
|
24
17
|
{
|
25
18
|
name: 'time',
|
26
19
|
import: 't',
|
@@ -402,7 +395,7 @@ export const BuiltinFuncs = function() {
|
|
402
395
|
|
403
396
|
// this is an implementation of xorshift128+ (in wasm bytecode)
|
404
397
|
// fun fact: v8, SM, JSC also use this (you will need this fun fact to maintain your sanity reading this code)
|
405
|
-
const prngSeed0 = Math.floor(Math.random() *
|
398
|
+
const prngSeed0 = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER), prngSeed1 = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
|
406
399
|
|
407
400
|
this.__Math_random = {
|
408
401
|
floatOnly: true,
|
@@ -416,13 +409,13 @@ export const BuiltinFuncs = function() {
|
|
416
409
|
wasm: [
|
417
410
|
// setup: s1 = state0, s0 = state1, state0 = s0
|
418
411
|
[ Opcodes.global_get, 0 ], // state0
|
419
|
-
[ Opcodes.
|
412
|
+
[ Opcodes.local_tee, 0 ], // s1
|
420
413
|
[ Opcodes.global_get, 1 ], // state1
|
421
414
|
[ Opcodes.local_tee, 1, ], // s0
|
422
415
|
[ Opcodes.global_set, 0 ], // state0
|
423
416
|
|
424
417
|
// s1 ^= s1 << 23
|
425
|
-
[ Opcodes.local_get, 0 ], // s1
|
418
|
+
// [ Opcodes.local_get, 0 ], // s1
|
426
419
|
[ Opcodes.local_get, 0 ], // s1
|
427
420
|
[ Opcodes.i64_const, 23 ],
|
428
421
|
[ Opcodes.i64_shl ], // <<
|
@@ -452,12 +445,26 @@ export const BuiltinFuncs = function() {
|
|
452
445
|
|
453
446
|
// you thought it was over? now we need the result as a f64 between 0-1 :)
|
454
447
|
|
455
|
-
//
|
448
|
+
// state1 + s0
|
456
449
|
[ Opcodes.global_get, 1 ], // state1
|
457
450
|
[ Opcodes.local_get, 1 ], // s0
|
458
451
|
[ Opcodes.i64_add ],
|
459
452
|
|
460
|
-
|
453
|
+
// should we >> 12 here?
|
454
|
+
// it feels like it but it breaks values
|
455
|
+
|
456
|
+
// | 0x3FF0000000000000
|
457
|
+
// [ Opcodes.i64_const, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf8, 0x3f ],
|
458
|
+
// [ Opcodes.i64_or ],
|
459
|
+
|
460
|
+
// bit cast as f64
|
461
|
+
// [ Opcodes.f64_reinterpret_i64 ],
|
462
|
+
|
463
|
+
// - 1
|
464
|
+
// ...number(1),
|
465
|
+
// [ Opcodes.f64_sub ],
|
466
|
+
|
467
|
+
...number((1 << 53) - 1, Valtype.i64),
|
461
468
|
[ Opcodes.i64_and ],
|
462
469
|
|
463
470
|
// double(mantissa)
|
@@ -568,7 +575,6 @@ export const BuiltinFuncs = function() {
|
|
568
575
|
params: [ Valtype.i32 ],
|
569
576
|
locals: [],
|
570
577
|
returns: [ Valtype.v128 ],
|
571
|
-
memory: true,
|
572
578
|
wasm: [
|
573
579
|
[ Opcodes.local_get, 0 ],
|
574
580
|
[ ...Opcodes.v128_load, 0, 0 ]
|