porffor 0.2.0-c6c8c81 → 0.2.0-c87ffeb
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/.vscode/launch.json +18 -0
- package/LICENSE +20 -20
- package/README.md +131 -71
- package/asur/README.md +2 -0
- package/asur/index.js +1262 -0
- package/byg/index.js +237 -0
- package/compiler/2c.js +325 -72
- package/compiler/{sections.js → assemble.js} +63 -15
- package/compiler/builtins/annexb_string.js +72 -0
- package/compiler/builtins/annexb_string.ts +19 -0
- package/compiler/builtins/array.ts +145 -0
- package/compiler/builtins/base64.ts +151 -0
- package/compiler/builtins/crypto.ts +120 -0
- package/compiler/builtins/date.ts +7 -0
- package/compiler/builtins/escape.ts +141 -0
- package/compiler/builtins/int.ts +147 -0
- package/compiler/builtins/number.ts +527 -0
- package/compiler/builtins/porffor.d.ts +42 -0
- package/compiler/builtins/string.ts +1055 -0
- package/compiler/builtins/tostring.ts +45 -0
- package/compiler/builtins.js +601 -269
- package/compiler/{codeGen.js → codegen.js} +1231 -472
- package/compiler/decompile.js +11 -12
- package/compiler/embedding.js +22 -22
- package/compiler/encoding.js +98 -114
- package/compiler/generated_builtins.js +695 -0
- package/compiler/index.js +40 -37
- package/compiler/log.js +6 -3
- package/compiler/opt.js +65 -29
- package/compiler/parse.js +42 -11
- package/compiler/precompile.js +123 -0
- package/compiler/prefs.js +26 -0
- package/compiler/prototype.js +177 -37
- package/compiler/types.js +37 -0
- package/compiler/wasmSpec.js +30 -7
- package/compiler/wrap.js +141 -45
- package/package.json +9 -5
- package/porf +4 -0
- package/rhemyn/compile.js +5 -3
- package/rhemyn/parse.js +323 -320
- package/rhemyn/test/parse.js +58 -58
- package/runner/compare.js +34 -34
- package/runner/debug.js +122 -0
- package/runner/index.js +49 -10
- package/runner/profiler.js +102 -0
- package/runner/repl.js +42 -9
- package/runner/sizes.js +37 -37
- package/test262_changes_from_1afe9b87d2_to_04-09.md +270 -0
- package/compiler/builtins/base64.js +0 -92
- package/runner/info.js +0 -89
- package/runner/profile.js +0 -46
- package/runner/results.json +0 -1
- package/runner/transform.js +0 -15
- package/util/enum.js +0 -20
package/compiler/2c.js
CHANGED
@@ -1,24 +1,106 @@
|
|
1
|
-
import { read_ieee754_binary64, read_signedLEB128 } from './encoding.js';
|
1
|
+
import { read_ieee754_binary64, read_signedLEB128, read_unsignedLEB128 } from './encoding.js';
|
2
2
|
import { Blocktype, Opcodes, Valtype } from './wasmSpec.js';
|
3
3
|
import { operatorOpcode } from './expression.js';
|
4
4
|
import { log } from "./log.js";
|
5
5
|
|
6
6
|
const CValtype = {
|
7
|
-
i8: '
|
8
|
-
i16: '
|
9
|
-
i32: '
|
10
|
-
|
11
|
-
i64: '
|
12
|
-
|
7
|
+
i8: 'i8',
|
8
|
+
i16: 'i16',
|
9
|
+
i32: 'i32',
|
10
|
+
u32: 'u32',
|
11
|
+
i64: 'i64',
|
12
|
+
u64: 'u64',
|
13
13
|
|
14
|
-
f32: '
|
15
|
-
f64: '
|
14
|
+
f32: 'f32',
|
15
|
+
f64: 'f64',
|
16
16
|
|
17
17
|
undefined: 'void'
|
18
18
|
};
|
19
19
|
|
20
|
+
const alwaysPreface = `typedef uint8_t i8;
|
21
|
+
typedef uint16_t i16;
|
22
|
+
typedef int32_t i32;
|
23
|
+
typedef uint32_t u32;
|
24
|
+
typedef int64_t i64;
|
25
|
+
typedef uint64_t u64;
|
26
|
+
typedef float f32;
|
27
|
+
typedef double f64;
|
28
|
+
|
29
|
+
f64 NAN = 0e+0/0e+0;
|
30
|
+
|
31
|
+
struct ReturnValue {
|
32
|
+
${CValtype.f64} value;
|
33
|
+
${CValtype.i32} type;
|
34
|
+
};\n\n`;
|
35
|
+
|
36
|
+
// todo: is memcpy/etc safe with host endianness?
|
37
|
+
|
38
|
+
// all:
|
39
|
+
// immediates: ['align', 'offset']
|
40
|
+
const CMemFuncs = {
|
41
|
+
[Opcodes.i32_store]: {
|
42
|
+
c: `memcpy(_memory + offset + pointer, &value, sizeof(value));`,
|
43
|
+
args: ['pointer', 'value'],
|
44
|
+
argTypes: [CValtype.i32, CValtype.i32],
|
45
|
+
returns: false
|
46
|
+
},
|
47
|
+
[Opcodes.i32_store16]: {
|
48
|
+
c: `memcpy(_memory + offset + pointer, &value, sizeof(value));`,
|
49
|
+
args: ['pointer', 'value'],
|
50
|
+
argTypes: [CValtype.i32, CValtype.i16],
|
51
|
+
returns: false
|
52
|
+
},
|
53
|
+
[Opcodes.i32_store8]: {
|
54
|
+
c: `memcpy(_memory + offset + pointer, &value, sizeof(value));`,
|
55
|
+
args: ['pointer', 'value'],
|
56
|
+
argTypes: [CValtype.i32, CValtype.i8],
|
57
|
+
returns: false
|
58
|
+
},
|
59
|
+
|
60
|
+
[Opcodes.i32_load]: {
|
61
|
+
c: `${CValtype.i32} out;
|
62
|
+
memcpy(&out, _memory + offset + pointer, sizeof(out));
|
63
|
+
return out;`,
|
64
|
+
args: ['pointer'],
|
65
|
+
argTypes: [CValtype.i32],
|
66
|
+
returns: CValtype.i32
|
67
|
+
},
|
68
|
+
[Opcodes.i32_load16_u]: {
|
69
|
+
c: `${CValtype.i16} out;
|
70
|
+
memcpy(&out, _memory + offset + pointer, sizeof(out));
|
71
|
+
return out;`,
|
72
|
+
args: ['pointer'],
|
73
|
+
argTypes: [CValtype.i32],
|
74
|
+
returns: CValtype.i32
|
75
|
+
},
|
76
|
+
[Opcodes.i32_load8_u]: {
|
77
|
+
c: `${CValtype.i8} out;
|
78
|
+
memcpy(&out, _memory + offset + pointer, sizeof(out));
|
79
|
+
return out;`,
|
80
|
+
args: ['pointer'],
|
81
|
+
argTypes: [CValtype.i32],
|
82
|
+
returns: CValtype.i32
|
83
|
+
},
|
84
|
+
|
85
|
+
[Opcodes.f64_store]: {
|
86
|
+
c: `memcpy(_memory + offset + pointer, &value, sizeof(value));`,
|
87
|
+
args: ['pointer', 'value'],
|
88
|
+
argTypes: [CValtype.i32, CValtype.f64],
|
89
|
+
returns: false
|
90
|
+
},
|
91
|
+
[Opcodes.f64_load]: {
|
92
|
+
c: `${CValtype.f64} out;
|
93
|
+
memcpy(&out, _memory + offset + pointer, sizeof(out));
|
94
|
+
return out;`,
|
95
|
+
args: ['pointer'],
|
96
|
+
argTypes: [CValtype.i32],
|
97
|
+
returns: CValtype.f64
|
98
|
+
},
|
99
|
+
};
|
100
|
+
|
20
101
|
const inv = (obj, keyMap = x => x) => Object.keys(obj).reduce((acc, x) => { acc[keyMap(obj[x])] = x; return acc; }, {});
|
21
102
|
const invOpcodes = inv(Opcodes);
|
103
|
+
const invValtype = inv(Valtype);
|
22
104
|
|
23
105
|
for (const x in CValtype) {
|
24
106
|
if (Valtype[x]) CValtype[Valtype[x]] = CValtype[x];
|
@@ -32,12 +114,22 @@ const todo = msg => {
|
|
32
114
|
}
|
33
115
|
}
|
34
116
|
|
35
|
-
throw new TodoError(
|
117
|
+
throw new TodoError(msg);
|
36
118
|
};
|
37
119
|
|
38
|
-
const removeBrackets = str =>
|
120
|
+
const removeBrackets = str => {
|
121
|
+
// return str;
|
122
|
+
// if (str.startsWith(`(${CValtype.i32})(${CValtype.u32})`)) return `(${CValtype.i32})(${CValtype.u32})(` + removeBrackets(str.slice(22, -1)) + ')';
|
123
|
+
|
124
|
+
for (const x in CValtype) {
|
125
|
+
const p = `(${x})`;
|
126
|
+
if (str.startsWith(p)) return p + removeBrackets(str.slice(p.length));
|
127
|
+
}
|
128
|
+
|
129
|
+
return str.startsWith('(') && str.endsWith(')') ? str.slice(1, -1) : str;
|
130
|
+
};
|
39
131
|
|
40
|
-
export default ({ funcs, globals, tags, exceptions, pages }) => {
|
132
|
+
export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
41
133
|
const invOperatorOpcode = Object.values(operatorOpcode).reduce((acc, x) => {
|
42
134
|
for (const k in x) {
|
43
135
|
acc[x[k]] = k;
|
@@ -53,12 +145,11 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
|
|
53
145
|
}
|
54
146
|
|
55
147
|
const includes = new Map(), unixIncludes = new Map(), winIncludes = new Map();
|
148
|
+
const prepend = new Map(), prependMain = new Map();
|
56
149
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
${CValtype.i32} type;
|
61
|
-
};\n\n`;
|
150
|
+
includes.set('stdint.h', true);
|
151
|
+
|
152
|
+
let out = ``;
|
62
153
|
|
63
154
|
for (const x in globals) {
|
64
155
|
const g = globals[x];
|
@@ -67,6 +158,15 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
|
|
67
158
|
out += ';\n';
|
68
159
|
}
|
69
160
|
|
161
|
+
if (pages.size > 0) {
|
162
|
+
prepend.set('_memory', `char _memory[${pages.size * pageSize}];\n`);
|
163
|
+
includes.set('string.h', true);
|
164
|
+
}
|
165
|
+
|
166
|
+
if (data.length > 0) {
|
167
|
+
prependMain.set('_data', data.map(x => `memcpy(_memory + ${x.offset}, (unsigned char[]){${x.bytes.join(',')}}, ${x.bytes.length});`).join('\n'));
|
168
|
+
}
|
169
|
+
|
70
170
|
// for (const [ x, p ] of pages) {
|
71
171
|
// out += `${CValtype[p.type]} ${x.replace(': ', '_').replace(/[^0-9a-zA-Z_]/g, '')}[100]`;
|
72
172
|
// out += ';\n';
|
@@ -75,7 +175,8 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
|
|
75
175
|
if (out) out += '\n';
|
76
176
|
|
77
177
|
let depth = 1;
|
78
|
-
|
178
|
+
let brDepth = 0;
|
179
|
+
const line = (str, semi = true) => out += `${' '.repeat(depth * 2 + brDepth * 2)}${str}${semi ? ';' : ''}\n`;
|
79
180
|
const lines = lines => {
|
80
181
|
for (const x of lines) {
|
81
182
|
out += `${' '.repeat(depth * 2)}${x}\n`;
|
@@ -108,6 +209,8 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
|
|
108
209
|
return tmp;
|
109
210
|
};
|
110
211
|
|
212
|
+
let brId = 0;
|
213
|
+
|
111
214
|
for (const f of funcs) {
|
112
215
|
depth = 1;
|
113
216
|
|
@@ -121,7 +224,12 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
|
|
121
224
|
const returns = f.returns.length > 0;
|
122
225
|
|
123
226
|
const shouldInline = f.internal;
|
124
|
-
out += `${f.name === 'main' ? 'int' : (f.internal ? '
|
227
|
+
out += `${f.name === 'main' ? 'int' : (f.internal ? (returns ? CValtype.f64 : 'void') : 'struct ReturnValue')} ${shouldInline ? 'inline ' : ''}${sanitize(f.name)}(${f.params.map((x, i) => `${CValtype[x]} ${invLocals[i]}`).join(', ')}) {\n`;
|
228
|
+
|
229
|
+
if (f.name === 'main') {
|
230
|
+
out += [...prependMain.values()].join('\n');
|
231
|
+
if (prependMain.size > 0) out += '\n\n';
|
232
|
+
}
|
125
233
|
|
126
234
|
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
235
|
for (const x of localKeys) {
|
@@ -131,11 +239,58 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
|
|
131
239
|
|
132
240
|
if (localKeys.length !== 0) out += '\n';
|
133
241
|
|
242
|
+
const rets = [];
|
243
|
+
const runOnEnd = [];
|
244
|
+
|
134
245
|
let vals = [];
|
135
|
-
const endNeedsCurly = []
|
136
|
-
|
246
|
+
const endNeedsCurly = [];
|
247
|
+
const brs = [];
|
248
|
+
let lastCond = false;
|
249
|
+
|
250
|
+
// let brDepth = 0;
|
251
|
+
|
252
|
+
const blockStart = (i, loop) => {
|
253
|
+
// reset "stack"
|
254
|
+
// vals = [];
|
255
|
+
|
256
|
+
rets.push(i[1]);
|
257
|
+
|
258
|
+
const br = brId++;
|
259
|
+
brs.push(br);
|
260
|
+
if (loop) {
|
261
|
+
line(`j${br}:;`, false);
|
262
|
+
runOnEnd.push(null);
|
263
|
+
} else {
|
264
|
+
runOnEnd.push(() => line(`j${br}:;`, false));
|
265
|
+
}
|
266
|
+
|
267
|
+
if (i[1] !== Blocktype.void) line(`${CValtype[i[1]]} _r${br}`);
|
268
|
+
|
269
|
+
brDepth++;
|
270
|
+
};
|
271
|
+
|
272
|
+
const highlight = i => {
|
273
|
+
const surrounding = 6;
|
274
|
+
|
275
|
+
const decomp = decompile(f.wasm.slice(i - surrounding, i + surrounding + 1), '', 0, f.locals, f.params, f.returns, funcs, globals, exceptions).slice(0, -1).split('\n');
|
276
|
+
|
277
|
+
const noAnsi = s => s.replace(/\u001b\[[0-9]+m/g, '');
|
278
|
+
let longest = 0;
|
279
|
+
for (let j = 0; j < decomp.length; j++) {
|
280
|
+
longest = Math.max(longest, noAnsi(decomp[j]).length);
|
281
|
+
}
|
282
|
+
|
283
|
+
const middle = Math.floor(decomp.length / 2);
|
284
|
+
decomp[middle] = `\x1B[47m\x1B[30m${noAnsi(decomp[middle])}${'\u00a0'.repeat(longest - noAnsi(decomp[middle]).length)}\x1B[0m`;
|
285
|
+
|
286
|
+
console.log('\x1B[90m...\x1B[0m');
|
287
|
+
console.log(decomp.join('\n'));
|
288
|
+
console.log('\x1B[90m...\x1B[0m\n');
|
289
|
+
};
|
290
|
+
|
137
291
|
for (let _ = 0; _ < f.wasm.length; _++) {
|
138
292
|
const i = f.wasm[_];
|
293
|
+
if (!i || !i[0]) continue;
|
139
294
|
|
140
295
|
if (invOperatorOpcode[i[0]]) {
|
141
296
|
const b = vals.pop();
|
@@ -157,12 +312,12 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
|
|
157
312
|
switch (i[1]) {
|
158
313
|
// i32_trunc_sat_f64_s
|
159
314
|
case 0x02:
|
160
|
-
vals.push(`(${CValtype.i32})${vals.pop()}`);
|
315
|
+
vals.push(`(${CValtype.i32})(${vals.pop()})`);
|
161
316
|
break;
|
162
317
|
|
163
318
|
// i32_trunc_sat_f64_u
|
164
319
|
case 0x03:
|
165
|
-
vals.push(`(${CValtype.
|
320
|
+
vals.push(`(${CValtype.u32})(${vals.pop()})`);
|
166
321
|
break;
|
167
322
|
}
|
168
323
|
|
@@ -173,12 +328,19 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
|
|
173
328
|
switch (i[0]) {
|
174
329
|
case Opcodes.i32_const:
|
175
330
|
case Opcodes.i64_const:
|
176
|
-
vals.push(read_signedLEB128(i.slice(1)).toString());
|
331
|
+
// vals.push(read_signedLEB128(i.slice(1)).toString());
|
332
|
+
vals.push(new String(read_signedLEB128(i.slice(1)).toString()));
|
333
|
+
vals.at(-1).offset = _;
|
177
334
|
break;
|
178
335
|
|
179
|
-
case Opcodes.f64_const:
|
180
|
-
|
336
|
+
case Opcodes.f64_const: {
|
337
|
+
// const val = read_ieee754_binary64(i.slice(1)).toExponential();
|
338
|
+
const val = new String(read_ieee754_binary64(i.slice(1)).toExponential());
|
339
|
+
// vals.push(val == 'NaN' ? 'NAN' : val);
|
340
|
+
vals.push(val == 'NaN' ? new String('NAN') : val);
|
341
|
+
vals.at(-1).offset = _;
|
181
342
|
break;
|
343
|
+
}
|
182
344
|
|
183
345
|
case Opcodes.local_get:
|
184
346
|
vals.push(`${invLocals[i[1]]}`);
|
@@ -189,9 +351,9 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
|
|
189
351
|
break;
|
190
352
|
|
191
353
|
case Opcodes.local_tee:
|
192
|
-
|
193
|
-
|
194
|
-
vals.push(`((${invLocals[i[1]]} = ${vals.pop()}))`);
|
354
|
+
line(`${invLocals[i[1]]} = ${removeBrackets(vals.pop())}`);
|
355
|
+
vals.push(`${invLocals[i[1]]}`);
|
356
|
+
// vals.push(`((${invLocals[i[1]]} = ${vals.pop()}))`);
|
195
357
|
break;
|
196
358
|
|
197
359
|
case Opcodes.global_get:
|
@@ -204,78 +366,102 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
|
|
204
366
|
|
205
367
|
case Opcodes.f64_trunc:
|
206
368
|
// vals.push(`trunc(${vals.pop()})`);
|
207
|
-
vals.push(`(
|
369
|
+
vals.push(`(${CValtype.i32})(${removeBrackets(vals.pop())})`); // this is ~10x faster with clang??
|
208
370
|
break;
|
209
371
|
|
210
372
|
case Opcodes.f64_convert_i32_u:
|
211
373
|
case Opcodes.f64_convert_i32_s:
|
212
374
|
case Opcodes.f64_convert_i64_u:
|
213
375
|
case Opcodes.f64_convert_i64_s:
|
214
|
-
// int to
|
215
|
-
vals.push(`(
|
376
|
+
// int to f64
|
377
|
+
vals.push(`(${CValtype.f64})(${removeBrackets(vals.pop())})`);
|
216
378
|
break;
|
217
379
|
|
380
|
+
case Opcodes.i32_eqz:
|
381
|
+
if (lastCond) {
|
382
|
+
vals.push(`!(${removeBrackets(vals.pop())})`);
|
383
|
+
} else {
|
384
|
+
let cond = '(' + removeBrackets(vals.pop());
|
385
|
+
if (cond.startsWith(`(${CValtype.i32})`)) cond = `${cond.slice(`(${CValtype.i32})`.length)}) == 0e+0`;
|
386
|
+
else cond += ') == 0';
|
387
|
+
vals.push(cond);
|
388
|
+
}
|
389
|
+
lastCond = true;
|
390
|
+
continue;
|
391
|
+
|
218
392
|
case Opcodes.return:
|
219
393
|
// line(`return${returns ? ` ${removeBrackets(vals.pop())}` : ''}`);
|
220
394
|
line(`return${returns ? ` (struct ReturnValue){ ${removeBrackets(vals.pop())}, ${removeBrackets(vals.pop())} }` : ''}`);
|
221
395
|
break;
|
222
396
|
|
223
|
-
case Opcodes.if:
|
397
|
+
case Opcodes.if: {
|
224
398
|
let cond = removeBrackets(vals.pop());
|
225
399
|
if (!lastCond) {
|
226
|
-
if (cond.startsWith(
|
227
|
-
else cond
|
400
|
+
if (cond.startsWith(`(${CValtype.i32})`)) cond = `(${cond.slice(`(${CValtype.i32})`.length)}) != 0e+0`;
|
401
|
+
else cond = `(${cond}) != 0`;
|
228
402
|
}
|
229
403
|
|
230
|
-
|
231
|
-
|
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
|
-
}
|
404
|
+
line(`// if ${invValtype[i[1]] ?? ''}`, false);
|
405
|
+
blockStart(i, false);
|
245
406
|
|
246
407
|
line(`if (${cond}) {`, false);
|
247
408
|
|
248
409
|
depth++;
|
249
410
|
endNeedsCurly.push(true);
|
250
|
-
ignoreEnd.push(false);
|
251
411
|
break;
|
412
|
+
}
|
252
413
|
|
253
|
-
case Opcodes.else:
|
254
|
-
|
414
|
+
case Opcodes.else: {
|
415
|
+
const br = brs.at(-1);
|
416
|
+
const ret = rets.at(-1);
|
417
|
+
if (ret && ret !== Blocktype.void) {
|
418
|
+
// console.log(vals, ret);
|
419
|
+
// console.log(decompile(f.wasm.slice(_ - 5, _ + 1)));
|
420
|
+
if (vals.length > 0) line(`_r${br} = ${removeBrackets(vals.pop())}`);
|
421
|
+
// vals.push(`_r${br}`);
|
422
|
+
}
|
255
423
|
|
256
424
|
depth--;
|
257
425
|
line(`} else {`, false);
|
258
426
|
depth++;
|
427
|
+
|
428
|
+
// reset "stack"
|
429
|
+
// vals = [];
|
259
430
|
break;
|
431
|
+
}
|
260
432
|
|
261
|
-
case Opcodes.loop:
|
262
|
-
|
263
|
-
|
433
|
+
case Opcodes.loop: {
|
434
|
+
line(`// loop ${invValtype[i[1]] ?? ''}`, false);
|
435
|
+
blockStart(i, true);
|
436
|
+
endNeedsCurly.push(false);
|
264
437
|
break;
|
438
|
+
}
|
265
439
|
|
266
|
-
case Opcodes.end:
|
267
|
-
|
440
|
+
case Opcodes.end: {
|
441
|
+
const br = brs.pop();
|
442
|
+
const ret = rets.pop();
|
443
|
+
if (ret && ret !== Blocktype.void) {
|
444
|
+
// console.log(vals, ret);
|
445
|
+
// console.log(decompile(f.wasm.slice(_ - 5, _ + 1)));
|
446
|
+
if (vals.length > 0) line(`_r${br} = ${removeBrackets(vals.pop())}`);
|
447
|
+
vals.push(`_r${br}`);
|
448
|
+
}
|
268
449
|
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
break;
|
450
|
+
const enc = endNeedsCurly.pop() === true;
|
451
|
+
if (enc) {
|
452
|
+
depth--;
|
453
|
+
line('}', false);
|
274
454
|
}
|
275
455
|
|
276
|
-
|
277
|
-
|
456
|
+
brDepth--;
|
457
|
+
|
458
|
+
line(`// end`, false);
|
459
|
+
|
460
|
+
const roe = runOnEnd.pop();
|
461
|
+
if (roe) roe();
|
462
|
+
|
278
463
|
break;
|
464
|
+
}
|
279
465
|
|
280
466
|
case Opcodes.call:
|
281
467
|
let func = funcs.find(x => x.index === i[1]);
|
@@ -283,7 +469,8 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
|
|
283
469
|
const importFunc = importFuncs[i[1]];
|
284
470
|
switch (importFunc.name) {
|
285
471
|
case 'print':
|
286
|
-
line(`printf("%f\\n", ${vals.pop()})`);
|
472
|
+
// line(`printf("%f\\n", ${vals.pop()})`);
|
473
|
+
line(`printf("${valtype === 'f64' ? '%g' : '%i'}\\n", ${vals.pop()})`);
|
287
474
|
includes.set('stdio.h', true);
|
288
475
|
break;
|
289
476
|
case 'printChar':
|
@@ -346,13 +533,74 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
346
533
|
vals.pop();
|
347
534
|
break;
|
348
535
|
|
349
|
-
case Opcodes.
|
350
|
-
|
351
|
-
|
352
|
-
|
536
|
+
case Opcodes.block:
|
537
|
+
line(`// block ${invValtype[i[1]] ?? ''}`, false);
|
538
|
+
blockStart(i, false);
|
539
|
+
endNeedsCurly.push(false);
|
540
|
+
break;
|
541
|
+
|
542
|
+
case Opcodes.br: {
|
543
|
+
const ret = rets[brDepth - i[1] - 1];
|
544
|
+
// console.log(rets, brDepth, i[1], brDepth - i[1] - 1, ret, vals);
|
545
|
+
if (ret !== Blocktype.void) line(`_r${brs[brDepth - i[1] - 1]} = ${removeBrackets(vals.pop())}`);
|
546
|
+
line(`goto j${brs[brDepth - i[1] - 1]}`);
|
547
|
+
|
548
|
+
// // reset "stack"
|
549
|
+
// vals = [];
|
353
550
|
break;
|
551
|
+
}
|
552
|
+
|
553
|
+
case Opcodes.br_if: {
|
554
|
+
const ret = rets[brDepth - i[1] - 1];
|
555
|
+
// console.log(rets, brDepth, i[1], brDepth - i[1] - 1, ret, vals);
|
556
|
+
|
557
|
+
let cond = removeBrackets(vals.pop());
|
558
|
+
if (!lastCond) {
|
559
|
+
if (cond.startsWith(`(${CValtype.i32})`)) cond = `(${cond.slice(`(${CValtype.i32})`.length)}) != 0e+0`;
|
560
|
+
else cond = `(${cond}) != 0`;
|
561
|
+
}
|
562
|
+
|
563
|
+
line(`if (${cond}) {`, false);
|
564
|
+
depth++;
|
565
|
+
if (ret !== Blocktype.void) line(`_r${brs[brDepth - i[1] - 1]} = ${removeBrackets(vals.at(-1))}`);
|
566
|
+
line(`goto j${brs[brDepth - i[1] - 1]}`);
|
567
|
+
depth--;
|
568
|
+
line(`}`, false);
|
569
|
+
|
570
|
+
break;
|
571
|
+
}
|
572
|
+
|
573
|
+
case Opcodes.throw: {
|
574
|
+
const id = vals.pop();
|
575
|
+
|
576
|
+
line(`printf("Uncaught ${exceptions[id].constructor}: ${exceptions[id].message}\\n")`);
|
577
|
+
line(`exit(1)`);
|
578
|
+
|
579
|
+
includes.set('stdlib.h', true);
|
580
|
+
|
581
|
+
break;
|
582
|
+
}
|
354
583
|
|
355
584
|
default:
|
585
|
+
if (CMemFuncs[i[0]]) {
|
586
|
+
const name = invOpcodes[i[0]];
|
587
|
+
const func = CMemFuncs[i[0]];
|
588
|
+
if (!prepend.has(name)) {
|
589
|
+
prepend.set(name, `${func.returns || 'void'} ${name}(${CValtype.i32} align, ${CValtype.i32} offset, ${func.args.map((x, i) => `${func.argTypes[i]} ${x}`).join(', ')}) {\n ${func.c.replaceAll('\n', '\n ')}\n}\n`);
|
590
|
+
// generate func c and prepend
|
591
|
+
}
|
592
|
+
|
593
|
+
const immediates = [ i[1], read_unsignedLEB128(i.slice(2)) ];
|
594
|
+
|
595
|
+
let args = [];
|
596
|
+
for (let j = 0; j < func.args.length; j++) args.unshift(removeBrackets(vals.pop()));
|
597
|
+
|
598
|
+
if (func.returns !== false) {
|
599
|
+
vals.push(`${name}(${immediates[0]}, ${immediates[1]}, ${args.join(', ')})`);
|
600
|
+
} else line(`${name}(${immediates[0]}, ${immediates[1]}, ${args.join(', ')})`);
|
601
|
+
break;
|
602
|
+
}
|
603
|
+
|
356
604
|
log.warning('2c', `unimplemented op: ${invOpcodes[i[0]]}`);
|
357
605
|
// todo(`unimplemented op: ${invOpcodes[i[0]]}`);
|
358
606
|
}
|
@@ -364,6 +612,11 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
364
612
|
line(`return ${vals.pop()}`);
|
365
613
|
}
|
366
614
|
|
615
|
+
if (f.name === 'main') {
|
616
|
+
out += '\n';
|
617
|
+
line(`return 0`);
|
618
|
+
}
|
619
|
+
|
367
620
|
out += '}\n\n';
|
368
621
|
}
|
369
622
|
|
@@ -371,7 +624,7 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
371
624
|
|
372
625
|
const makeIncludes = includes => [...includes.keys()].map(x => `#include <${x}>\n`).join('');
|
373
626
|
|
374
|
-
out = platformSpecific(makeIncludes(winIncludes), makeIncludes(unixIncludes), false) + '\n' + makeIncludes(includes) + '\n' + out;
|
627
|
+
out = platformSpecific(makeIncludes(winIncludes), makeIncludes(unixIncludes), false) + '\n' + makeIncludes(includes) + '\n' + alwaysPreface + [...prepend.values()].join('\n') + '\n\n' + out;
|
375
628
|
|
376
|
-
return out;
|
629
|
+
return out.trim();
|
377
630
|
};
|