porffor 0.55.20 → 0.55.22
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/builtins/bigint.ts +4 -8
- package/compiler/codegen.js +102 -182
- package/package.json +1 -1
- package/r.cjs +6 -0
- package/runner/index.js +1 -1
@@ -5,11 +5,11 @@ export const __Porffor_bigint_fromDigits = (negative: boolean, digits: i32[]): b
|
|
5
5
|
const len: i32 = digits.length;
|
6
6
|
if (len > 16383) throw new RangeError('Maximum BigInt size exceeded'); // (65536 - 4) / 4
|
7
7
|
|
8
|
-
//
|
8
|
+
// use digits pointer as bigint pointer, as only used here
|
9
9
|
let ptr: i32 = Porffor.wasm`local.get ${digits}`;
|
10
10
|
|
11
|
-
Porffor.wasm.i32.store8(ptr, negative ? 1 : 0, 0, 0);
|
12
|
-
Porffor.wasm.i32.store16(ptr, len, 0, 2);
|
11
|
+
Porffor.wasm.i32.store8(ptr, negative ? 1 : 0, 0, 0); // sign
|
12
|
+
Porffor.wasm.i32.store16(ptr, len, 0, 2); // digit count
|
13
13
|
|
14
14
|
let allZero: boolean = true;
|
15
15
|
for (let i: i32 = 0; i < len; i++) {
|
@@ -84,14 +84,10 @@ export const __Porffor_bigint_fromString = (n: string|bytestring): bigint => {
|
|
84
84
|
offset = 1;
|
85
85
|
}
|
86
86
|
|
87
|
-
// n ->
|
88
|
-
// 4294967294 -> [ 4294967294 ]
|
87
|
+
// n -> base 2^32 digits (most to least significant)
|
89
88
|
// 4294967295 -> [ 4294967295 ]
|
90
89
|
// 4294967296 -> [ 1, 0 ]
|
91
90
|
// 4294967297 -> [ 1, 1 ]
|
92
|
-
// 9007199254740992 -> [ 2097152, 0 ]
|
93
|
-
// 9007199254740993 -> [ 2097152, 1 ]
|
94
|
-
// 9007199254740994 -> [ 2097152, 2 ]
|
95
91
|
|
96
92
|
const BASE: i32 = 0x100000000; // 2^32
|
97
93
|
const digits: i32[] = Porffor.allocate(); // todo: free later
|
package/compiler/codegen.js
CHANGED
@@ -10,14 +10,6 @@ import { log } from './log.js';
|
|
10
10
|
import { allocPage, allocStr } from './allocator.js';
|
11
11
|
import './prefs.js';
|
12
12
|
|
13
|
-
let globals = {};
|
14
|
-
let tags = [];
|
15
|
-
let funcs = [];
|
16
|
-
let exceptions = [];
|
17
|
-
let funcIndex = {};
|
18
|
-
let currentFuncIndex = importedFuncs.length;
|
19
|
-
let builtinFuncs = {}, builtinVars = {}, prototypeFuncs = {};
|
20
|
-
|
21
13
|
class TodoError extends Error {
|
22
14
|
constructor(message) {
|
23
15
|
super(message);
|
@@ -46,7 +38,6 @@ const cacheAst = (decl, wasm) => {
|
|
46
38
|
return wasm;
|
47
39
|
};
|
48
40
|
|
49
|
-
let indirectFuncs = [];
|
50
41
|
let doNotMarkFuncRef = false;
|
51
42
|
const funcRef = func => {
|
52
43
|
if (!doNotMarkFuncRef) func.referenced = true;
|
@@ -462,7 +453,7 @@ const lookup = (scope, name, failEarly = false) => {
|
|
462
453
|
}
|
463
454
|
|
464
455
|
if (local?.idx === undefined) {
|
465
|
-
if (name === 'arguments' &&
|
456
|
+
if (name === 'arguments' && !scope.arrow) {
|
466
457
|
// todo: not compliant
|
467
458
|
let len = countLength(scope);
|
468
459
|
const names = new Array(len);
|
@@ -1386,29 +1377,6 @@ const generateLogicExp = (scope, decl) => {
|
|
1386
1377
|
return performLogicOp(scope, decl.operator, generate(scope, decl.left), generate(scope, decl.right), getNodeType(scope, decl.left), getNodeType(scope, decl.right));
|
1387
1378
|
};
|
1388
1379
|
|
1389
|
-
// potential future ideas for nan boxing (unused):
|
1390
|
-
// T = JS type, V = value/pointer
|
1391
|
-
// 0bTTT
|
1392
|
-
// qNAN: 0 11111111111 1000000000000000000000000000000000000000000000000001
|
1393
|
-
// 50 bits usable: 0 11111111111 11??????????????????????????????????????????????????
|
1394
|
-
// js type: 4 bits
|
1395
|
-
// internal type: ? bits
|
1396
|
-
// pointer: 32 bits
|
1397
|
-
// https://piotrduperas.com/posts/nan-boxing
|
1398
|
-
// 0x7ffc000000000000
|
1399
|
-
// budget: 50 bits
|
1400
|
-
// js type: 4 bits
|
1401
|
-
// internal type: ? bits
|
1402
|
-
// pointer: 32 bits
|
1403
|
-
// generic
|
1404
|
-
// 1 23 4 5
|
1405
|
-
// 0 11111111111 11TTTTIIII??????????PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
|
1406
|
-
// 1: regular iEEE 754 double NaN
|
1407
|
-
// 2: extra 1 bit to identify NaN box
|
1408
|
-
// 3: js type
|
1409
|
-
// 4: internal type
|
1410
|
-
// 5: pointer
|
1411
|
-
|
1412
1380
|
const isExistingProtoFunc = name => {
|
1413
1381
|
if (name.startsWith('__Array_prototype')) return !!prototypeFuncs[TYPES.array][name.slice(18)];
|
1414
1382
|
if (name.startsWith('__String_prototype_')) return !!prototypeFuncs[TYPES.string][name.slice(19)];
|
@@ -1416,7 +1384,6 @@ const isExistingProtoFunc = name => {
|
|
1416
1384
|
return false;
|
1417
1385
|
};
|
1418
1386
|
|
1419
|
-
let globalInfer;
|
1420
1387
|
const getInferred = (scope, name, global = false) => {
|
1421
1388
|
if (global) {
|
1422
1389
|
if (globalInfer.has(name)) return globalInfer.get(name);
|
@@ -1470,7 +1437,7 @@ const getType = (scope, name, failEarly = false) => {
|
|
1470
1437
|
global = true;
|
1471
1438
|
}
|
1472
1439
|
|
1473
|
-
if (global !== false && name === 'arguments' &&
|
1440
|
+
if (global !== false && name === 'arguments' && !scope.arrow) {
|
1474
1441
|
return [ number(TYPES.array, Valtype.i32) ];
|
1475
1442
|
}
|
1476
1443
|
|
@@ -2750,18 +2717,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2750
2717
|
}
|
2751
2718
|
|
2752
2719
|
out.push([ Opcodes.call, idx ]);
|
2753
|
-
|
2754
|
-
if (!typedReturns) {
|
2755
|
-
// let type;
|
2756
|
-
// if (builtinFuncs[name]) type = TYPES[builtinFuncs[name].returnType ?? 'number'];
|
2757
|
-
// if (internalConstrs[name]) type = internalConstrs[name].type;
|
2758
|
-
// if (importedFuncs[name] && importedFuncs[]) type =
|
2759
|
-
|
2760
|
-
// if (type) out.push(
|
2761
|
-
// number(type, Valtype.i32),
|
2762
|
-
// [ Opcodes.local_set, localTmp(scope, '#last_type', Valtype.i32) ]
|
2763
|
-
// );
|
2764
|
-
} else out.push(...setLastType(scope));
|
2720
|
+
if (typedReturns) out.push(...setLastType(scope));
|
2765
2721
|
|
2766
2722
|
if (
|
2767
2723
|
func?.returns?.length === 0 ||
|
@@ -2941,8 +2897,7 @@ const brTable = (input, bc, returns) => {
|
|
2941
2897
|
for (let i = offset; i <= max; i++) {
|
2942
2898
|
// if branch for this num, go to that block
|
2943
2899
|
if (bc[i]) {
|
2944
|
-
table.push(br);
|
2945
|
-
br++;
|
2900
|
+
table.push(br++);
|
2946
2901
|
continue;
|
2947
2902
|
}
|
2948
2903
|
|
@@ -2979,9 +2934,6 @@ const brTable = (input, bc, returns) => {
|
|
2979
2934
|
return out;
|
2980
2935
|
};
|
2981
2936
|
|
2982
|
-
let typeswitchDepth = 0;
|
2983
|
-
|
2984
|
-
let usedTypes = new Set();
|
2985
2937
|
const typeUsed = (scope, x) => {
|
2986
2938
|
if (x == null) return;
|
2987
2939
|
usedTypes.add(x);
|
@@ -3137,7 +3089,7 @@ const typeIsNotOneOf = (type, types, valtype = Valtype.i32) => {
|
|
3137
3089
|
return out;
|
3138
3090
|
};
|
3139
3091
|
|
3140
|
-
const allocVar = (scope, name, global = false, type = true, redecl = false) => {
|
3092
|
+
const allocVar = (scope, name, global = false, type = true, redecl = false, i32 = false) => {
|
3141
3093
|
const target = global ? globals : scope.locals;
|
3142
3094
|
|
3143
3095
|
// already declared
|
@@ -3152,7 +3104,7 @@ const allocVar = (scope, name, global = false, type = true, redecl = false) => {
|
|
3152
3104
|
}
|
3153
3105
|
|
3154
3106
|
let idx = global ? globals['#ind']++ : scope.localInd++;
|
3155
|
-
target[name] = { idx, type: valtypeBinary };
|
3107
|
+
target[name] = { idx, type: i32 ? Valtype.i32 : valtypeBinary };
|
3156
3108
|
|
3157
3109
|
if (type) {
|
3158
3110
|
let typeIdx = global ? globals['#ind']++ : scope.localInd++;
|
@@ -3571,9 +3523,8 @@ const generateVarDstr = (scope, kind, pattern, init, defaultValue, global) => {
|
|
3571
3523
|
const generateVar = (scope, decl) => {
|
3572
3524
|
let out = [];
|
3573
3525
|
|
3574
|
-
const topLevel = scope.name === '#main';
|
3575
|
-
|
3576
3526
|
// global variable if in top scope (main) or if internally wanted
|
3527
|
+
const topLevel = scope.name === '#main';
|
3577
3528
|
const global = decl._global ?? (topLevel || decl._bare);
|
3578
3529
|
|
3579
3530
|
for (const x of decl.declarations) {
|
@@ -3635,8 +3586,16 @@ const memberTmpNames = scope => {
|
|
3635
3586
|
};
|
3636
3587
|
|
3637
3588
|
// COCTC: cross-object compile-time cache
|
3638
|
-
let coctc = new Map();
|
3639
3589
|
const coctcOffset = prop => {
|
3590
|
+
if (typeof prop === 'object') {
|
3591
|
+
if (
|
3592
|
+
prop.computed || prop.optional ||
|
3593
|
+
['prototype', 'size', 'description', 'byteLength', 'byteOffset', 'buffer', 'detached', 'resizable', 'growable', 'maxByteLength', 'length', '__proto__'].includes(prop.property.name)
|
3594
|
+
) return 0;
|
3595
|
+
|
3596
|
+
prop = prop.property.name;
|
3597
|
+
}
|
3598
|
+
|
3640
3599
|
let offset = coctc.get(prop);
|
3641
3600
|
if (offset == null) {
|
3642
3601
|
offset = (coctc.lastOffset ?? 60000) - 9;
|
@@ -3768,7 +3727,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
3768
3727
|
// todo/perf: use i32 object (and prop?) locals
|
3769
3728
|
const { objectTmp, propertyTmp, objectGet, propertyGet } = memberTmpNames(scope);
|
3770
3729
|
|
3771
|
-
const useCoctc = Prefs.coctc &&
|
3730
|
+
const useCoctc = Prefs.coctc && coctcOffset(decl.left) > 0;
|
3772
3731
|
if (useCoctc) valueUnused = false;
|
3773
3732
|
|
3774
3733
|
// opt: do not mark prototype funcs as referenced to optimize this in them
|
@@ -4214,7 +4173,7 @@ const generateUnary = (scope, decl) => {
|
|
4214
4173
|
const property = getProperty(decl.argument);
|
4215
4174
|
if (property.value === 'length' || property.value === 'name') scope.noFastFuncMembers = true;
|
4216
4175
|
|
4217
|
-
const useCoctc = Prefs.coctc &&
|
4176
|
+
const useCoctc = Prefs.coctc && coctcOffset(decl.argument) > 0;
|
4218
4177
|
const objectTmp = useCoctc && localTmp(scope, '#coctc_object', Valtype.i32);
|
4219
4178
|
|
4220
4179
|
const out = [
|
@@ -4453,7 +4412,6 @@ const generateConditional = (scope, decl) => {
|
|
4453
4412
|
return out;
|
4454
4413
|
};
|
4455
4414
|
|
4456
|
-
let depth = [];
|
4457
4415
|
const generateFor = (scope, decl) => {
|
4458
4416
|
const out = [];
|
4459
4417
|
|
@@ -5390,9 +5348,6 @@ const generateMeta = (scope, decl) => {
|
|
5390
5348
|
return todo(scope, `meta property object ${decl.meta.name} is not supported yet`, true);
|
5391
5349
|
};
|
5392
5350
|
|
5393
|
-
let pages = new Map();
|
5394
|
-
let data = [];
|
5395
|
-
|
5396
5351
|
const compileBytes = (val, itemType) => {
|
5397
5352
|
switch (itemType) {
|
5398
5353
|
case 'i8': return [ val % 256 ];
|
@@ -5410,7 +5365,7 @@ const makeData = (scope, elements, page = null, itemType = 'i8') => {
|
|
5410
5365
|
|
5411
5366
|
const length = elements.length;
|
5412
5367
|
|
5413
|
-
// if length is 0 memory/data will just be 0000... anyway
|
5368
|
+
// if length is 0, memory/data will just be 0000... anyway
|
5414
5369
|
if (length === 0) return false;
|
5415
5370
|
|
5416
5371
|
let bytes = compileBytes(length, 'i32');
|
@@ -5424,7 +5379,6 @@ const makeData = (scope, elements, page = null, itemType = 'i8') => {
|
|
5424
5379
|
}
|
5425
5380
|
|
5426
5381
|
const obj = { bytes, page };
|
5427
|
-
|
5428
5382
|
const idx = data.push(obj) - 1;
|
5429
5383
|
|
5430
5384
|
scope.data ??= [];
|
@@ -5448,63 +5402,6 @@ const printStaticStr = str => {
|
|
5448
5402
|
return out;
|
5449
5403
|
};
|
5450
5404
|
|
5451
|
-
const storeArray = (scope, array, index, element) => {
|
5452
|
-
if (!Array.isArray(element)) element = generate(scope, element);
|
5453
|
-
if (typeof index === 'number') index = [ number(index) ];
|
5454
|
-
|
5455
|
-
const offset = localTmp(scope, '#storeArray_offset', Valtype.i32);
|
5456
|
-
|
5457
|
-
return [
|
5458
|
-
// calculate offset
|
5459
|
-
...index,
|
5460
|
-
Opcodes.i32_to_u,
|
5461
|
-
number(ValtypeSize[valtype] + 1, Valtype.i32),
|
5462
|
-
[ Opcodes.i32_mul ],
|
5463
|
-
|
5464
|
-
...array,
|
5465
|
-
Opcodes.i32_to_u,
|
5466
|
-
[ Opcodes.i32_add ],
|
5467
|
-
[ Opcodes.local_set, offset ],
|
5468
|
-
|
5469
|
-
// store value
|
5470
|
-
[ Opcodes.local_get, offset ],
|
5471
|
-
...generate(scope, element),
|
5472
|
-
[ Opcodes.store, 0, ValtypeSize.i32 ],
|
5473
|
-
|
5474
|
-
// store type
|
5475
|
-
[ Opcodes.local_get, offset ],
|
5476
|
-
...getNodeType(scope, element),
|
5477
|
-
[ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
5478
|
-
];
|
5479
|
-
};
|
5480
|
-
|
5481
|
-
const loadArray = (scope, array, index) => {
|
5482
|
-
if (typeof index === 'number') index = [ number(index) ];
|
5483
|
-
|
5484
|
-
const offset = localTmp(scope, '#loadArray_offset', Valtype.i32);
|
5485
|
-
|
5486
|
-
return [
|
5487
|
-
// calculate offset
|
5488
|
-
...index,
|
5489
|
-
Opcodes.i32_to_u,
|
5490
|
-
number(ValtypeSize[valtype] + 1, Valtype.i32),
|
5491
|
-
[ Opcodes.i32_mul ],
|
5492
|
-
|
5493
|
-
...array,
|
5494
|
-
Opcodes.i32_to_u,
|
5495
|
-
[ Opcodes.i32_add ],
|
5496
|
-
[ Opcodes.local_set, offset ],
|
5497
|
-
|
5498
|
-
// load value
|
5499
|
-
[ Opcodes.local_get, offset ],
|
5500
|
-
[ Opcodes.load, 0, ValtypeSize.i32 ],
|
5501
|
-
|
5502
|
-
// load type
|
5503
|
-
[ Opcodes.local_get, offset ],
|
5504
|
-
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
5505
|
-
];
|
5506
|
-
};
|
5507
|
-
|
5508
5405
|
const byteStringable = str => {
|
5509
5406
|
for (let i = 0; i < str.length; i++) {
|
5510
5407
|
if (str.charCodeAt(i) > 0xFF) return false;
|
@@ -5943,14 +5840,27 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
5943
5840
|
}
|
5944
5841
|
}
|
5945
5842
|
|
5946
|
-
const useCoctc = Prefs.coctc &&
|
5843
|
+
const useCoctc = Prefs.coctc && coctcOffset(decl) > 0;
|
5947
5844
|
const coctcObjTmp = useCoctc && localTmp(scope, '#coctc_obj' + uniqId(), Valtype.i32);
|
5948
5845
|
|
5949
5846
|
const out = typeSwitch(scope, getNodeType(scope, object), {
|
5950
5847
|
...(decl.computed ? {
|
5951
5848
|
[TYPES.array]: () => [
|
5952
|
-
|
5953
|
-
|
5849
|
+
propertyGet,
|
5850
|
+
Opcodes.i32_to_u,
|
5851
|
+
number(ValtypeSize[valtype] + 1, Valtype.i32),
|
5852
|
+
[ Opcodes.i32_mul ],
|
5853
|
+
|
5854
|
+
objectGet,
|
5855
|
+
Opcodes.i32_to_u,
|
5856
|
+
[ Opcodes.i32_add ],
|
5857
|
+
[ Opcodes.local_tee, localTmp(scope, '#loadArray_offset', Valtype.i32) ],
|
5858
|
+
[ Opcodes.load, 0, ValtypeSize.i32 ],
|
5859
|
+
|
5860
|
+
...setLastType(scope, [
|
5861
|
+
[ Opcodes.local_get, localTmp(scope, '#loadArray_offset', Valtype.i32) ],
|
5862
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ],
|
5863
|
+
])
|
5954
5864
|
],
|
5955
5865
|
|
5956
5866
|
[TYPES.string]: () => [
|
@@ -6291,18 +6201,6 @@ const generateClass = (scope, decl) => {
|
|
6291
6201
|
// default value to undefined
|
6292
6202
|
value ??= DEFAULT_VALUE();
|
6293
6203
|
|
6294
|
-
let outArr = out, outOp = 'push', outScope = scope;
|
6295
|
-
if (type === 'PropertyDefinition' && !_static) {
|
6296
|
-
// define in construction instead
|
6297
|
-
outArr = func.wasm;
|
6298
|
-
outOp = 'unshift';
|
6299
|
-
object = {
|
6300
|
-
type: 'ThisExpression',
|
6301
|
-
_noGlobalThis: true
|
6302
|
-
};
|
6303
|
-
outScope = func;
|
6304
|
-
}
|
6305
|
-
|
6306
6204
|
if (isFuncType(value.type)) {
|
6307
6205
|
let id = value.id;
|
6308
6206
|
|
@@ -6320,19 +6218,60 @@ const generateClass = (scope, decl) => {
|
|
6320
6218
|
};
|
6321
6219
|
}
|
6322
6220
|
|
6323
|
-
|
6324
|
-
|
6325
|
-
|
6326
|
-
|
6221
|
+
if (type === 'PropertyDefinition' && !_static) {
|
6222
|
+
// define in construction instead
|
6223
|
+
object = {
|
6224
|
+
type: 'ThisExpression',
|
6225
|
+
_noGlobalThis: true
|
6226
|
+
};
|
6327
6227
|
|
6328
|
-
|
6228
|
+
let computedTmp;
|
6229
|
+
if (computed) {
|
6230
|
+
// compute now, reference in construction
|
6231
|
+
computedTmp = allocVar(scope, `#class_computed_prop${uniqId()}`, true, true, false, true);
|
6329
6232
|
|
6330
|
-
|
6331
|
-
|
6332
|
-
|
6233
|
+
out.push(
|
6234
|
+
...toPropertyKey(scope, generate(scope, k), getNodeType(scope, k), computed, true),
|
6235
|
+
[ Opcodes.global_set, computedTmp + 1 ],
|
6236
|
+
[ Opcodes.global_set, computedTmp ]
|
6237
|
+
);
|
6238
|
+
}
|
6333
6239
|
|
6334
|
-
|
6335
|
-
|
6240
|
+
func.wasm.unshift(
|
6241
|
+
...generate(func, object),
|
6242
|
+
Opcodes.i32_to_u,
|
6243
|
+
...getNodeType(func, object),
|
6244
|
+
|
6245
|
+
...(computed ? [
|
6246
|
+
[ Opcodes.global_get, computedTmp ],
|
6247
|
+
[ Opcodes.global_get, computedTmp + 1 ],
|
6248
|
+
] : [
|
6249
|
+
...generate(func, k),
|
6250
|
+
Opcodes.i32_to_u,
|
6251
|
+
...getNodeType(func, k)
|
6252
|
+
]),
|
6253
|
+
|
6254
|
+
...generate(func, value),
|
6255
|
+
...(initKind !== 'value' && initKind !== 'method' ? [ Opcodes.i32_to_u ] : []),
|
6256
|
+
...getNodeType(func, value),
|
6257
|
+
|
6258
|
+
[ Opcodes.call, includeBuiltin(func, `__Porffor_object_class_${initKind}`).index ]
|
6259
|
+
);
|
6260
|
+
} else {
|
6261
|
+
out.push(
|
6262
|
+
...generate(scope, object),
|
6263
|
+
Opcodes.i32_to_u,
|
6264
|
+
...getNodeType(scope, object),
|
6265
|
+
|
6266
|
+
...toPropertyKey(scope, generate(scope, k), getNodeType(scope, k), computed, true),
|
6267
|
+
|
6268
|
+
...generate(scope, value),
|
6269
|
+
...(initKind !== 'value' && initKind !== 'method' ? [ Opcodes.i32_to_u ] : []),
|
6270
|
+
...getNodeType(scope, value),
|
6271
|
+
|
6272
|
+
[ Opcodes.call, includeBuiltin(scope, `__Porffor_object_class_${initKind}`).index ]
|
6273
|
+
);
|
6274
|
+
}
|
6336
6275
|
}
|
6337
6276
|
|
6338
6277
|
delete scope.overrideThis;
|
@@ -6855,7 +6794,6 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6855
6794
|
return [ func, out ];
|
6856
6795
|
};
|
6857
6796
|
|
6858
|
-
let largestBlockBody = 0;
|
6859
6797
|
const generateBlock = (scope, decl) => {
|
6860
6798
|
let out = [];
|
6861
6799
|
|
@@ -6863,10 +6801,8 @@ const generateBlock = (scope, decl) => {
|
|
6863
6801
|
scope.inferTree.push(decl);
|
6864
6802
|
|
6865
6803
|
let len = decl.body.length, j = 0;
|
6866
|
-
if (len > largestBlockBody) largestBlockBody = len;
|
6867
6804
|
for (let i = 0; i < len; i++) {
|
6868
6805
|
const x = decl.body[i];
|
6869
|
-
if (len >= largestBlockBody) globalThis.progress?.(`${i}/${len}`);
|
6870
6806
|
if (isEmptyNode(x)) continue;
|
6871
6807
|
|
6872
6808
|
if (j++ > 0) out.push([ Opcodes.drop ]);
|
@@ -7029,10 +6965,9 @@ const internalConstrs = {
|
|
7029
6965
|
}
|
7030
6966
|
};
|
7031
6967
|
|
6968
|
+
let globals, tags, exceptions, funcs, indirectFuncs, funcIndex, currentFuncIndex, depth, pages, data, typeswitchDepth, usedTypes, coctc, globalInfer, builtinFuncs, builtinVars, prototypeFuncs;
|
7032
6969
|
export default program => {
|
7033
|
-
globals = {
|
7034
|
-
['#ind']: 0
|
7035
|
-
};
|
6970
|
+
globals = { ['#ind']: 0 };
|
7036
6971
|
tags = [];
|
7037
6972
|
exceptions = [];
|
7038
6973
|
funcs = []; indirectFuncs = [];
|
@@ -7042,26 +6977,22 @@ export default program => {
|
|
7042
6977
|
data = [];
|
7043
6978
|
currentFuncIndex = importedFuncs.length;
|
7044
6979
|
typeswitchDepth = 0;
|
7045
|
-
largestBlockBody = 0;
|
7046
6980
|
usedTypes = new Set([ TYPES.empty, TYPES.undefined, TYPES.number, TYPES.boolean, TYPES.function ]);
|
7047
6981
|
coctc = new Map();
|
7048
6982
|
globalInfer = new Map();
|
7049
6983
|
|
7050
|
-
const valtypeInd = ['i32', 'i64', 'f64'].indexOf(valtype);
|
7051
|
-
|
7052
6984
|
// set generic opcodes for current valtype
|
6985
|
+
const valtypeInd = ['i32', 'i64', 'f64'].indexOf(valtype);
|
7053
6986
|
Opcodes.const = [ Opcodes.i32_const, Opcodes.i64_const, Opcodes.f64_const ][valtypeInd];
|
7054
6987
|
Opcodes.eq = [ Opcodes.i32_eq, Opcodes.i64_eq, Opcodes.f64_eq ][valtypeInd];
|
7055
6988
|
Opcodes.eqz = [ [ [ Opcodes.i32_eqz ] ], [ [ Opcodes.i64_eqz ] ], [ number(0), [ Opcodes.f64_eq ] ] ][valtypeInd];
|
7056
6989
|
Opcodes.mul = [ Opcodes.i32_mul, Opcodes.i64_mul, Opcodes.f64_mul ][valtypeInd];
|
7057
6990
|
Opcodes.add = [ Opcodes.i32_add, Opcodes.i64_add, Opcodes.f64_add ][valtypeInd];
|
7058
6991
|
Opcodes.sub = [ Opcodes.i32_sub, Opcodes.i64_sub, Opcodes.f64_sub ][valtypeInd];
|
7059
|
-
|
7060
6992
|
Opcodes.i32_to = [ [], [ Opcodes.i32_wrap_i64 ], Opcodes.i32_trunc_sat_f64_s ][valtypeInd];
|
7061
6993
|
Opcodes.i32_to_u = [ [], [ Opcodes.i32_wrap_i64 ], Opcodes.i32_trunc_sat_f64_u ][valtypeInd];
|
7062
6994
|
Opcodes.i32_from = [ [], [ Opcodes.i64_extend_i32_s ], [ Opcodes.f64_convert_i32_s ] ][valtypeInd];
|
7063
6995
|
Opcodes.i32_from_u = [ [], [ Opcodes.i64_extend_i32_u ], [ Opcodes.f64_convert_i32_u ] ][valtypeInd];
|
7064
|
-
|
7065
6996
|
Opcodes.load = [ Opcodes.i32_load, Opcodes.i64_load, Opcodes.f64_load ][valtypeInd];
|
7066
6997
|
Opcodes.store = [ Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store ][valtypeInd];
|
7067
6998
|
|
@@ -7072,28 +7003,24 @@ export default program => {
|
|
7072
7003
|
const getObjectName = x => x.startsWith('__') && x.slice(2, x.indexOf('_', 2));
|
7073
7004
|
objectHackers = ['assert', 'compareArray', 'Test262Error', ...new Set(Object.keys(builtinFuncs).map(getObjectName).concat(Object.keys(builtinVars).map(getObjectName)).filter(x => x))];
|
7074
7005
|
|
7075
|
-
|
7076
|
-
|
7077
|
-
|
7078
|
-
|
7079
|
-
|
7080
|
-
|
7081
|
-
|
7082
|
-
|
7083
|
-
|
7084
|
-
const [ main ] = generateFunc({}, program);
|
7006
|
+
const [ main ] = generateFunc({}, {
|
7007
|
+
type: 'Program',
|
7008
|
+
id: { name: '#main' },
|
7009
|
+
body: {
|
7010
|
+
type: 'BlockStatement',
|
7011
|
+
body: program.body
|
7012
|
+
}
|
7013
|
+
});
|
7085
7014
|
|
7086
7015
|
// if wanted and blank main func and other exports, remove it
|
7087
7016
|
if (Prefs.rmBlankMain && main.wasm.length === 0 && funcs.some(x => x.export)) funcs.splice(main.index - importedFuncs.length, 1);
|
7088
7017
|
|
7089
|
-
// make ~empty funcs for never generated funcs
|
7090
|
-
// todo: these should just be deleted once able
|
7091
7018
|
for (let i = 0; i < funcs.length; i++) {
|
7092
7019
|
const f = funcs[i];
|
7093
7020
|
|
7094
|
-
|
7095
|
-
|
7096
|
-
|
7021
|
+
const wasm = f.wasm;
|
7022
|
+
if (wasm) {
|
7023
|
+
// func was generated, run callback ops
|
7097
7024
|
for (let j = 0; j < wasm.length; j++) {
|
7098
7025
|
const o = wasm[j];
|
7099
7026
|
if (o[0] === null && typeof o[1] === 'function') {
|
@@ -7104,14 +7031,8 @@ export default program => {
|
|
7104
7031
|
continue;
|
7105
7032
|
}
|
7106
7033
|
|
7107
|
-
// make wasm just return 0s for expected returns
|
7034
|
+
// func was never generated, make wasm just return 0s for expected returns
|
7108
7035
|
f.wasm = f.returns.map(x => number(0, x));
|
7109
|
-
|
7110
|
-
// alternative: make func empty, may break some indirect calls
|
7111
|
-
// f.wasm = [];
|
7112
|
-
// f.returns = [];
|
7113
|
-
// f.params = [];
|
7114
|
-
// f.locals = {};
|
7115
7036
|
}
|
7116
7037
|
|
7117
7038
|
// // remove never generated functions
|
@@ -7151,10 +7072,9 @@ export default program => {
|
|
7151
7072
|
for (let i = 0; i < indirectFuncs.length; i++) {
|
7152
7073
|
const f = indirectFuncs[i];
|
7153
7074
|
f.index = currentFuncIndex++;
|
7075
|
+
funcs.push(f);
|
7154
7076
|
}
|
7155
7077
|
|
7156
|
-
funcs.push(...indirectFuncs);
|
7157
|
-
|
7158
7078
|
delete globals['#ind'];
|
7159
7079
|
|
7160
7080
|
return { funcs, globals, tags, exceptions, pages, data };
|
package/package.json
CHANGED
package/r.cjs
CHANGED