porffor 0.17.0-b103c8894 → 0.17.0-b598eb7bb
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/compiler/2c.js +28 -11
- package/compiler/builtins/array.ts +1 -1
- package/compiler/builtins.js +11 -0
- package/compiler/codegen.js +161 -25
- package/compiler/generated_builtins.js +30 -30
- package/compiler/pgo.js +9 -1
- package/compiler/wrap.js +6 -4
- package/package.json +1 -1
- package/rhemyn/README.md +7 -4
- package/rhemyn/compile.js +139 -73
- package/runner/debug.js +1 -1
- package/runner/index.js +3 -3
- package/runner/profile.js +1 -1
- package/runner/repl.js +5 -5
package/compiler/2c.js
CHANGED
@@ -182,7 +182,15 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
182
182
|
}, {});
|
183
183
|
const invGlobals = inv(globals, x => x.idx);
|
184
184
|
|
185
|
-
const
|
185
|
+
const codeToSanitizedStr = code => {
|
186
|
+
let out = '';
|
187
|
+
while (code > 0) {
|
188
|
+
out += String.fromCharCode(97 + code % 26);
|
189
|
+
code -= 26;
|
190
|
+
}
|
191
|
+
return out;
|
192
|
+
};
|
193
|
+
const sanitize = str => str.replace(/[^0-9a-zA-Z_]/g, _ => codeToSanitizedStr(_.charCodeAt(0)));
|
186
194
|
|
187
195
|
for (const x in invGlobals) {
|
188
196
|
invGlobals[x] = sanitize(invGlobals[x]);
|
@@ -273,10 +281,11 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
273
281
|
}
|
274
282
|
|
275
283
|
const returns = f.returns.length > 0;
|
284
|
+
const typedReturns = f.returnType == null;
|
276
285
|
|
277
286
|
const shouldInline = false; // f.internal;
|
278
287
|
if (f.name === 'main') out += `int main(${prependMain.has('argv') ? 'int argc, char* argv[]' : ''}) {\n`;
|
279
|
-
else out += `${
|
288
|
+
else out += `${!typedReturns ? (returns ? CValtype[f.returns[0]] : 'void') : 'struct ReturnValue'} ${shouldInline ? 'inline ' : ''}${sanitize(f.name)}(${f.params.map((x, i) => `${CValtype[x]} ${invLocals[i]}`).join(', ')}) {\n`;
|
280
289
|
|
281
290
|
if (f.name === 'main') {
|
282
291
|
out += ' ' + [...prependMain.values()].join('\n ');
|
@@ -418,11 +427,14 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
418
427
|
continue;
|
419
428
|
|
420
429
|
case Opcodes.return:
|
421
|
-
|
422
|
-
|
423
|
-
|
430
|
+
if (!typedReturns) {
|
431
|
+
line(`return${returns ? ` ${removeBrackets(vals.pop())}` : ''}`);
|
432
|
+
break;
|
433
|
+
}
|
434
|
+
|
435
|
+
const b = returns ? vals.pop() : -1;
|
436
|
+
const a = returns ? vals.pop() : -1;
|
424
437
|
line(`return${returns ? ` (struct ReturnValue){ ${removeBrackets(a)}, ${removeBrackets(b)} }` : ''}`);
|
425
|
-
// line(`return${returns ? ` (struct ReturnValue){ ${removeBrackets(vals.pop())}, ${removeBrackets(vals.pop())} }` : ''}`);
|
426
438
|
break;
|
427
439
|
|
428
440
|
case Opcodes.if: {
|
@@ -549,10 +561,15 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
549
561
|
|
550
562
|
prepend.set('__Porffor_readFile',
|
551
563
|
`i32 __Porffor_readFile(u32 pathPtr, u32 outPtr) {
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
564
|
+
FILE* fp;
|
565
|
+
if (pathPtr == 0) {
|
566
|
+
fp = stdin;
|
567
|
+
} else {
|
568
|
+
char* path = _memory + pathPtr + 4;
|
569
|
+
fp = fopen(path, "r");
|
570
|
+
if (fp == NULL) {
|
571
|
+
return -1;
|
572
|
+
}
|
556
573
|
}
|
557
574
|
|
558
575
|
u32 read = 0;
|
@@ -585,7 +602,7 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
585
602
|
for (let j = 0; j < func.params.length; j++) args.unshift(removeBrackets(vals.pop()));
|
586
603
|
|
587
604
|
if (func.returns.length > 0) {
|
588
|
-
if (func.
|
605
|
+
if (func.returnType != null) {
|
589
606
|
vals.push(`${sanitize(func.name)}(${args.join(', ')})`);
|
590
607
|
} else {
|
591
608
|
const id = retTmpId++;
|
package/compiler/builtins.js
CHANGED
@@ -160,6 +160,17 @@ export const BuiltinVars = function() {
|
|
160
160
|
this.__performance_timeOrigin = [
|
161
161
|
[ Opcodes.call, importedFuncs.timeOrigin ]
|
162
162
|
];
|
163
|
+
|
164
|
+
|
165
|
+
this.__Uint8Array_BYTES_PER_ELEMENT = number(1);
|
166
|
+
this.__Int8Array_BYTES_PER_ELEMENT = number(1);
|
167
|
+
this.__Uint8ClampedArray_BYTES_PER_ELEMENT = number(1);
|
168
|
+
this.__Uint16Array_BYTES_PER_ELEMENT = number(2);
|
169
|
+
this.__Int16Array_BYTES_PER_ELEMENT = number(2);
|
170
|
+
this.__Uint32Array_BYTES_PER_ELEMENT = number(4);
|
171
|
+
this.__Int32Array_BYTES_PER_ELEMENT = number(4);
|
172
|
+
this.__Float32Array_BYTES_PER_ELEMENT = number(4);
|
173
|
+
this.__Float64Array_BYTES_PER_ELEMENT = number(8);
|
163
174
|
};
|
164
175
|
|
165
176
|
export const BuiltinFuncs = function() {
|
package/compiler/codegen.js
CHANGED
@@ -619,11 +619,14 @@ const compareStrings = (scope, left, right, bytestrings = false) => {
|
|
619
619
|
};
|
620
620
|
|
621
621
|
const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMode = undefined) => {
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
622
|
+
if (isIntToFloatOp(wasm[wasm.length - 1])) return [
|
623
|
+
...wasm,
|
624
|
+
...(!intIn && intOut ? [ Opcodes.i32_to_u ] : [])
|
625
|
+
];
|
626
|
+
if (isIntOp(wasm[wasm.length - 1])) return [
|
627
|
+
...wasm,
|
628
|
+
...(intOut ? [] : [ Opcodes.i32_from ]),
|
629
|
+
];
|
627
630
|
|
628
631
|
// todo/perf: use knownType and custom bytecode here instead of typeSwitch
|
629
632
|
|
@@ -1417,9 +1420,9 @@ const countLeftover = wasm => {
|
|
1417
1420
|
|
1418
1421
|
if (depth === 0)
|
1419
1422
|
if ([Opcodes.throw, Opcodes.drop, Opcodes.local_set, Opcodes.global_set].includes(inst[0])) count--;
|
1420
|
-
else if ([null, Opcodes.i32_eqz, Opcodes.i64_eqz, Opcodes.f64_ceil, Opcodes.f64_floor, Opcodes.f64_trunc, Opcodes.f64_nearest, Opcodes.f64_sqrt, Opcodes.local_tee, Opcodes.i32_wrap_i64, Opcodes.i64_extend_i32_s, Opcodes.i64_extend_i32_u, Opcodes.f32_demote_f64, Opcodes.f64_promote_f32, Opcodes.f64_convert_i32_s, Opcodes.f64_convert_i32_u, Opcodes.i32_clz, Opcodes.i32_ctz, Opcodes.i32_popcnt, Opcodes.f64_neg, Opcodes.end, Opcodes.i32_trunc_sat_f64_s[0], Opcodes.i32x4_extract_lane, Opcodes.i16x8_extract_lane, Opcodes.i32_load, Opcodes.i64_load, Opcodes.f64_load, Opcodes.v128_load, Opcodes.i32_load16_u, Opcodes.i32_load16_s, Opcodes.i32_load8_u, Opcodes.i32_load8_s, Opcodes.memory_grow].includes(inst[0]) && (inst[0] !== 0xfc || inst[1] < 0x04)) {}
|
1423
|
+
else if ([null, Opcodes.i32_eqz, Opcodes.i64_eqz, Opcodes.f64_ceil, Opcodes.f64_floor, Opcodes.f64_trunc, Opcodes.f64_nearest, Opcodes.f64_sqrt, Opcodes.local_tee, Opcodes.i32_wrap_i64, Opcodes.i64_extend_i32_s, Opcodes.i64_extend_i32_u, Opcodes.f32_demote_f64, Opcodes.f64_promote_f32, Opcodes.f64_convert_i32_s, Opcodes.f64_convert_i32_u, Opcodes.i32_clz, Opcodes.i32_ctz, Opcodes.i32_popcnt, Opcodes.f64_neg, Opcodes.end, Opcodes.i32_trunc_sat_f64_s[0], Opcodes.i32x4_extract_lane, Opcodes.i16x8_extract_lane, Opcodes.i32_load, Opcodes.i64_load, Opcodes.f64_load, Opcodes.f32_load, Opcodes.v128_load, Opcodes.i32_load16_u, Opcodes.i32_load16_s, Opcodes.i32_load8_u, Opcodes.i32_load8_s, Opcodes.memory_grow].includes(inst[0]) && (inst[0] !== 0xfc || inst[1] < 0x04)) {}
|
1421
1424
|
else if ([Opcodes.local_get, Opcodes.global_get, Opcodes.f64_const, Opcodes.i32_const, Opcodes.i64_const, Opcodes.v128_const, Opcodes.memory_size].includes(inst[0])) count++;
|
1422
|
-
else if ([Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store, Opcodes.i32_store16, Opcodes.i32_store8].includes(inst[0])) count -= 2;
|
1425
|
+
else if ([Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store, Opcodes.f32_store, Opcodes.i32_store16, Opcodes.i32_store8].includes(inst[0])) count -= 2;
|
1423
1426
|
else if (inst[0] === Opcodes.memory_copy[0] && (inst[1] === Opcodes.memory_copy[1] || inst[1] === Opcodes.memory_init[1])) count -= 3;
|
1424
1427
|
else if (inst[0] === Opcodes.return) count = 0;
|
1425
1428
|
else if (inst[0] === Opcodes.call) {
|
@@ -1587,9 +1590,9 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1587
1590
|
if (!name && decl.callee.type === 'MemberExpression') {
|
1588
1591
|
// megahack for /regex/.func()
|
1589
1592
|
const funcName = decl.callee.property.name;
|
1590
|
-
if (decl.callee.object.regex &&
|
1593
|
+
if (decl.callee.object.regex && ['test'].includes(funcName)) {
|
1591
1594
|
const regex = decl.callee.object.regex.pattern;
|
1592
|
-
const rhemynName = `regex_${funcName}_${regex}`;
|
1595
|
+
const rhemynName = `regex_${funcName}_${sanitize(regex)}`;
|
1593
1596
|
|
1594
1597
|
if (!funcIndex[rhemynName]) {
|
1595
1598
|
const func = Rhemyn[funcName](regex, currentFuncIndex++, rhemynName);
|
@@ -1610,7 +1613,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1610
1613
|
[ Opcodes.call, idx ],
|
1611
1614
|
Opcodes.i32_from_u,
|
1612
1615
|
|
1613
|
-
...setLastType(scope,
|
1616
|
+
...setLastType(scope, Rhemyn.types[funcName])
|
1614
1617
|
];
|
1615
1618
|
}
|
1616
1619
|
|
@@ -1619,24 +1622,44 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1619
1622
|
target = decl.callee.object;
|
1620
1623
|
}
|
1621
1624
|
|
1622
|
-
|
1623
|
-
|
1625
|
+
if (protoName) {
|
1626
|
+
if (['search'].includes(protoName)) {
|
1627
|
+
const regex = decl.arguments[0]?.regex?.pattern;
|
1628
|
+
if (!regex) return [
|
1629
|
+
// no/bad regex arg, return -1/0 for now
|
1630
|
+
...generate(scope, target),
|
1631
|
+
[ Opcodes.drop ],
|
1624
1632
|
|
1625
|
-
|
1626
|
-
|
1633
|
+
...number(Rhemyn.types[protoName] === TYPES.number ? -1 : 0),
|
1634
|
+
...setLastType(scope, Rhemyn.types[protoName])
|
1635
|
+
];
|
1627
1636
|
|
1628
|
-
|
1629
|
-
// generate(scope, decl.callee.object)
|
1637
|
+
const rhemynName = `regex_${protoName}_${sanitize(regex)}`;
|
1630
1638
|
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
// ];
|
1635
|
-
// }
|
1639
|
+
if (!funcIndex[rhemynName]) {
|
1640
|
+
const func = Rhemyn[protoName](regex, currentFuncIndex++, rhemynName);
|
1641
|
+
func.internal = true;
|
1636
1642
|
|
1637
|
-
|
1638
|
-
|
1643
|
+
funcIndex[func.name] = func.index;
|
1644
|
+
funcs.push(func);
|
1645
|
+
}
|
1646
|
+
|
1647
|
+
const idx = funcIndex[rhemynName];
|
1648
|
+
return [
|
1649
|
+
// make string arg
|
1650
|
+
...generate(scope, target),
|
1651
|
+
Opcodes.i32_to_u,
|
1652
|
+
...getNodeType(scope, target),
|
1653
|
+
|
1654
|
+
// call regex func
|
1655
|
+
[ Opcodes.call, idx ],
|
1656
|
+
Opcodes.i32_from,
|
1639
1657
|
|
1658
|
+
...setLastType(scope, Rhemyn.types[protoName])
|
1659
|
+
];
|
1660
|
+
}
|
1661
|
+
|
1662
|
+
const protoBC = {};
|
1640
1663
|
const builtinProtoCands = Object.keys(builtinFuncs).filter(x => x.startsWith('__') && x.endsWith('_prototype_' + protoName));
|
1641
1664
|
|
1642
1665
|
if (!decl._protoInternalCall && builtinProtoCands.length > 0) {
|
@@ -2050,6 +2073,16 @@ const DEFAULT_VALUE = {
|
|
2050
2073
|
name: 'undefined'
|
2051
2074
|
};
|
2052
2075
|
|
2076
|
+
const codeToSanitizedStr = code => {
|
2077
|
+
let out = '';
|
2078
|
+
while (code > 0) {
|
2079
|
+
out += String.fromCharCode(97 + code % 26);
|
2080
|
+
code -= 26;
|
2081
|
+
}
|
2082
|
+
return out;
|
2083
|
+
};
|
2084
|
+
const sanitize = str => str.replace(/[^0-9a-zA-Z_]/g, _ => codeToSanitizedStr(_.charCodeAt(0)));
|
2085
|
+
|
2053
2086
|
const unhackName = name => {
|
2054
2087
|
if (name.startsWith('__')) return name.slice(2).replaceAll('_', '.');
|
2055
2088
|
return name;
|
@@ -2953,7 +2986,9 @@ const generateForOf = (scope, decl) => {
|
|
2953
2986
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
2954
2987
|
// hack: this is naughty and will break things!
|
2955
2988
|
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
2956
|
-
|
2989
|
+
|
2990
|
+
const known = knownType(scope, getNodeType(scope, decl.right));
|
2991
|
+
if ((known === TYPES.string || known === TYPES.bytestring) || (pages.hasAnyString && known == null)) {
|
2957
2992
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
2958
2993
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
2959
2994
|
rawElements: new Array(0)
|
@@ -3001,6 +3036,7 @@ const generateForOf = (scope, decl) => {
|
|
3001
3036
|
[ Opcodes.end ],
|
3002
3037
|
[ Opcodes.end ]
|
3003
3038
|
],
|
3039
|
+
|
3004
3040
|
[TYPES.string]: [
|
3005
3041
|
...setType(scope, leftName, TYPES.string),
|
3006
3042
|
|
@@ -3109,6 +3145,7 @@ const generateForOf = (scope, decl) => {
|
|
3109
3145
|
[ Opcodes.end ],
|
3110
3146
|
[ Opcodes.end ]
|
3111
3147
|
],
|
3148
|
+
|
3112
3149
|
[TYPES.set]: [
|
3113
3150
|
[ Opcodes.loop, Blocktype.void ],
|
3114
3151
|
|
@@ -3147,7 +3184,106 @@ const generateForOf = (scope, decl) => {
|
|
3147
3184
|
[ Opcodes.end ],
|
3148
3185
|
[ Opcodes.end ]
|
3149
3186
|
],
|
3150
|
-
|
3187
|
+
|
3188
|
+
...wrapBC({
|
3189
|
+
[TYPES.uint8array]: [
|
3190
|
+
[ Opcodes.i32_add ],
|
3191
|
+
|
3192
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3193
|
+
Opcodes.i32_from_u
|
3194
|
+
],
|
3195
|
+
[TYPES.uint8clampedarray]: [
|
3196
|
+
[ Opcodes.i32_add ],
|
3197
|
+
|
3198
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3199
|
+
Opcodes.i32_from_u
|
3200
|
+
],
|
3201
|
+
[TYPES.int8array]: [
|
3202
|
+
[ Opcodes.i32_add ],
|
3203
|
+
|
3204
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
3205
|
+
Opcodes.i32_from
|
3206
|
+
],
|
3207
|
+
[TYPES.uint16array]: [
|
3208
|
+
...number(2, Valtype.i32),
|
3209
|
+
[ Opcodes.i32_mul ],
|
3210
|
+
[ Opcodes.i32_add ],
|
3211
|
+
|
3212
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
3213
|
+
Opcodes.i32_from_u
|
3214
|
+
],
|
3215
|
+
[TYPES.int16array]: [
|
3216
|
+
...number(2, Valtype.i32),
|
3217
|
+
[ Opcodes.i32_mul ],
|
3218
|
+
[ Opcodes.i32_add ],
|
3219
|
+
|
3220
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
3221
|
+
Opcodes.i32_from
|
3222
|
+
],
|
3223
|
+
[TYPES.uint32array]: [
|
3224
|
+
...number(4, Valtype.i32),
|
3225
|
+
[ Opcodes.i32_mul ],
|
3226
|
+
[ Opcodes.i32_add ],
|
3227
|
+
|
3228
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3229
|
+
Opcodes.i32_from_u
|
3230
|
+
],
|
3231
|
+
[TYPES.int32array]: [
|
3232
|
+
...number(4, Valtype.i32),
|
3233
|
+
[ Opcodes.i32_mul ],
|
3234
|
+
[ Opcodes.i32_add ],
|
3235
|
+
|
3236
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3237
|
+
Opcodes.i32_from
|
3238
|
+
],
|
3239
|
+
[TYPES.float32array]: [
|
3240
|
+
...number(4, Valtype.i32),
|
3241
|
+
[ Opcodes.i32_mul ],
|
3242
|
+
[ Opcodes.i32_add ],
|
3243
|
+
|
3244
|
+
[ Opcodes.f32_load, 0, 4 ],
|
3245
|
+
[ Opcodes.f64_promote_f32 ]
|
3246
|
+
],
|
3247
|
+
[TYPES.float64array]: [
|
3248
|
+
...number(8, Valtype.i32),
|
3249
|
+
[ Opcodes.i32_mul ],
|
3250
|
+
[ Opcodes.i32_add ],
|
3251
|
+
|
3252
|
+
[ Opcodes.f64_load, 0, 4 ]
|
3253
|
+
],
|
3254
|
+
}, {
|
3255
|
+
prelude: [
|
3256
|
+
...setType(scope, leftName, TYPES.number),
|
3257
|
+
|
3258
|
+
[ Opcodes.loop, Blocktype.void ],
|
3259
|
+
|
3260
|
+
[ Opcodes.local_get, pointer ],
|
3261
|
+
[ Opcodes.local_get, counter ]
|
3262
|
+
],
|
3263
|
+
postlude: [
|
3264
|
+
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
3265
|
+
|
3266
|
+
[ Opcodes.block, Blocktype.void ],
|
3267
|
+
[ Opcodes.block, Blocktype.void ],
|
3268
|
+
...generate(scope, decl.body),
|
3269
|
+
[ Opcodes.end ],
|
3270
|
+
|
3271
|
+
// increment counter by 1
|
3272
|
+
[ Opcodes.local_get, counter ],
|
3273
|
+
...number(1, Valtype.i32),
|
3274
|
+
[ Opcodes.i32_add ],
|
3275
|
+
[ Opcodes.local_tee, counter ],
|
3276
|
+
|
3277
|
+
// loop if counter != length
|
3278
|
+
[ Opcodes.local_get, length ],
|
3279
|
+
[ Opcodes.i32_ne ],
|
3280
|
+
[ Opcodes.br_if, 1 ],
|
3281
|
+
|
3282
|
+
[ Opcodes.end ],
|
3283
|
+
[ Opcodes.end ]
|
3284
|
+
]
|
3285
|
+
}),
|
3286
|
+
|
3151
3287
|
default: internalThrow(scope, 'TypeError', `Tried for..of on non-iterable type`)
|
3152
3288
|
}, Blocktype.void));
|
3153
3289
|
|