porffor 0.55.21 → 0.55.23
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/allocator.js +1 -1
- package/compiler/builtins/_internal_object.ts +560 -279
- package/compiler/builtins/bigint.ts +2 -2
- package/compiler/builtins/function.ts +1 -1
- package/compiler/builtins/object.ts +35 -44
- package/compiler/builtins/object_prototypeWithHidden.js +47 -0
- package/compiler/builtins/reflect.ts +4 -4
- package/compiler/builtins/z_ecma262.ts +3 -0
- package/compiler/builtins_precompiled.js +569 -550
- package/compiler/codegen.js +124 -198
- package/compiler/precompile.js +6 -5
- package/compiler/prototype.js +80 -66
- package/compiler/wrap.js +3 -4
- package/package.json +1 -1
- package/r.cjs +29 -0
- package/runner/index.js +1 -1
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;
|
@@ -1393,7 +1384,6 @@ const isExistingProtoFunc = name => {
|
|
1393
1384
|
return false;
|
1394
1385
|
};
|
1395
1386
|
|
1396
|
-
let globalInfer;
|
1397
1387
|
const getInferred = (scope, name, global = false) => {
|
1398
1388
|
if (global) {
|
1399
1389
|
if (globalInfer.has(name)) return globalInfer.get(name);
|
@@ -1549,7 +1539,7 @@ const getNodeType = (scope, node) => {
|
|
1549
1539
|
return getType(scope, node.name);
|
1550
1540
|
}
|
1551
1541
|
|
1552
|
-
if (node.type === 'ObjectExpression') {
|
1542
|
+
if (node.type === 'ObjectExpression' || node.type === 'Super') {
|
1553
1543
|
return TYPES.object;
|
1554
1544
|
}
|
1555
1545
|
|
@@ -1581,24 +1571,6 @@ const getNodeType = (scope, node) => {
|
|
1581
1571
|
if (Object.hasOwn(builtinFuncs, name) && builtinFuncs[name].returnType != null) return builtinFuncs[name].returnType;
|
1582
1572
|
if (Object.hasOwn(internalConstrs, name) && internalConstrs[name].type != null) return internalConstrs[name].type;
|
1583
1573
|
|
1584
|
-
// check if this is a prototype function
|
1585
|
-
// if so and there is only one impl (eg charCodeAt)
|
1586
|
-
// or all impls have the same return type
|
1587
|
-
// use that return type as that is the only possibility
|
1588
|
-
// (if non-matching type it would error out)
|
1589
|
-
if (name.startsWith('__')) {
|
1590
|
-
const spl = name.slice(2).split('_');
|
1591
|
-
|
1592
|
-
const func = spl[spl.length - 1];
|
1593
|
-
const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES.bytestring && prototypeFuncs[x][func] != null);
|
1594
|
-
if (
|
1595
|
-
protoFuncs.length === 1 ||
|
1596
|
-
(protoFuncs.length > 1 && protoFuncs.every(x => x.returnType === protoFuncs[0].returnType))
|
1597
|
-
) {
|
1598
|
-
if (protoFuncs[0].returnType != null) return protoFuncs[0].returnType;
|
1599
|
-
}
|
1600
|
-
}
|
1601
|
-
|
1602
1574
|
if (name.startsWith('__Porffor_wasm_')) {
|
1603
1575
|
// todo: return undefined for non-returning ops
|
1604
1576
|
return TYPES.number;
|
@@ -1870,29 +1842,6 @@ const createNewTarget = (scope, decl, idx = 0, force = false) => {
|
|
1870
1842
|
];
|
1871
1843
|
};
|
1872
1844
|
|
1873
|
-
const makeObject = (scope, obj) => {
|
1874
|
-
const properties = [];
|
1875
|
-
for (const x in obj) {
|
1876
|
-
properties.push({
|
1877
|
-
type: 'Property',
|
1878
|
-
method: false,
|
1879
|
-
shorthand: false,
|
1880
|
-
computed: false,
|
1881
|
-
key: {
|
1882
|
-
type: 'Identifier',
|
1883
|
-
name: x
|
1884
|
-
},
|
1885
|
-
value: obj[x],
|
1886
|
-
kind: 'init'
|
1887
|
-
});
|
1888
|
-
}
|
1889
|
-
|
1890
|
-
return generate(scope, {
|
1891
|
-
type: 'ObjectExpression',
|
1892
|
-
properties
|
1893
|
-
});
|
1894
|
-
};
|
1895
|
-
|
1896
1845
|
const getObjProp = (obj, prop) => {
|
1897
1846
|
if (typeof obj === 'string') obj = {
|
1898
1847
|
type: 'Identifier',
|
@@ -1977,32 +1926,22 @@ const createThisArg = (scope, decl) => {
|
|
1977
1926
|
number(TYPES.object, Valtype.i32)
|
1978
1927
|
];
|
1979
1928
|
|
1980
|
-
// create new object with
|
1929
|
+
// create new object with prototype set to callee prototype
|
1981
1930
|
const tmp = localTmp(scope, '#this_create_tmp');
|
1982
1931
|
const proto = getObjProp(decl.callee, 'prototype');
|
1983
1932
|
|
1984
1933
|
return [
|
1985
|
-
|
1934
|
+
[ Opcodes.call, includeBuiltin(scope, '__Porffor_allocate').index ],
|
1935
|
+
Opcodes.i32_from_u,
|
1986
1936
|
[ Opcodes.local_tee, tmp ],
|
1987
1937
|
Opcodes.i32_to_u,
|
1988
|
-
|
1989
1938
|
number(TYPES.object, Valtype.i32),
|
1990
1939
|
|
1991
|
-
...generate(scope, {
|
1992
|
-
type: 'Literal',
|
1993
|
-
value: '__proto__'
|
1994
|
-
}),
|
1995
|
-
Opcodes.i32_to_u,
|
1996
|
-
number(TYPES.bytestring, Valtype.i32),
|
1997
|
-
|
1998
1940
|
...generate(scope, proto),
|
1941
|
+
Opcodes.i32_to_u,
|
1999
1942
|
...getNodeType(scope, proto),
|
2000
1943
|
|
2001
|
-
|
2002
|
-
number(0b1000, Valtype.i32),
|
2003
|
-
number(TYPES.number, Valtype.i32),
|
2004
|
-
|
2005
|
-
[ Opcodes.call, includeBuiltin(scope, '__Porffor_object_expr_initWithFlags').index ],
|
1944
|
+
[ Opcodes.call, includeBuiltin(scope, '__Porffor_object_setPrototype').index ],
|
2006
1945
|
|
2007
1946
|
[ Opcodes.local_get, tmp ],
|
2008
1947
|
number(TYPES.object, Valtype.i32)
|
@@ -2363,30 +2302,34 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2363
2302
|
const protoLocal2 = protoFunc.local2 ? localTmp(scope, `__${protoName}_tmp2`, protoFunc.local2) : -1;
|
2364
2303
|
|
2365
2304
|
let optUnused = false;
|
2366
|
-
const protoOut = protoFunc(
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2373
|
-
|
2374
|
-
|
2375
|
-
|
2376
|
-
|
2377
|
-
|
2378
|
-
|
2379
|
-
|
2380
|
-
|
2381
|
-
|
2382
|
-
|
2383
|
-
|
2305
|
+
const protoOut = protoFunc({
|
2306
|
+
pointer: getPointer,
|
2307
|
+
length: {
|
2308
|
+
getCachedI32: () => [ [ Opcodes.local_get, lengthLocal ] ],
|
2309
|
+
setCachedI32: () => [ [ Opcodes.local_set, lengthLocal ] ],
|
2310
|
+
get: () => ArrayUtil.getLength(getPointer),
|
2311
|
+
getI32: () => ArrayUtil.getLengthI32(getPointer),
|
2312
|
+
set: value => ArrayUtil.setLength(getPointer, value),
|
2313
|
+
setI32: value => ArrayUtil.setLengthI32(getPointer, value)
|
2314
|
+
},
|
2315
|
+
arg: generate(scope, decl.arguments[0] ?? DEFAULT_VALUE()),
|
2316
|
+
argType: getNodeType(scope, decl.arguments[0] ?? DEFAULT_VALUE()),
|
2317
|
+
iTmp: protoLocal,
|
2318
|
+
iTmp2: protoLocal2,
|
2319
|
+
alloc: bytes => [
|
2320
|
+
number(bytes, Valtype.i32),
|
2321
|
+
[ Opcodes.call, includeBuiltin(scope, '__Porffor_allocateBytes').index ]
|
2322
|
+
],
|
2323
|
+
unusedValue: () => {
|
2324
|
+
optUnused = true;
|
2325
|
+
return unusedValue;
|
2326
|
+
},
|
2327
|
+
setType: type => setLastType(scope, type)
|
2384
2328
|
});
|
2385
2329
|
|
2386
2330
|
return [
|
2387
2331
|
[ Opcodes.block, unusedValue ? Blocktype.void : valtypeBinary ],
|
2388
2332
|
...protoOut,
|
2389
|
-
...(unusedValue && optUnused ? [] : (protoFunc.returnType != null ? setLastType(scope, protoFunc.returnType) : setLastType(scope))),
|
2390
2333
|
...(unusedValue && !optUnused ? [ [ Opcodes.drop ] ] : []),
|
2391
2334
|
[ Opcodes.end ]
|
2392
2335
|
];
|
@@ -2784,8 +2727,19 @@ const generateThis = (scope, decl) => {
|
|
2784
2727
|
];
|
2785
2728
|
};
|
2786
2729
|
|
2787
|
-
const generateSuper = (scope, decl) => generate(scope,
|
2788
|
-
|
2730
|
+
const generateSuper = (scope, decl) => generate(scope, {
|
2731
|
+
type: 'CallExpression',
|
2732
|
+
callee: { type: 'Identifier', name: '__Porffor_object_getPrototype' },
|
2733
|
+
arguments: [
|
2734
|
+
{
|
2735
|
+
type: 'CallExpression',
|
2736
|
+
callee: { type: 'Identifier', name: '__Porffor_object_getPrototype' },
|
2737
|
+
arguments: [
|
2738
|
+
{ type: 'ThisExpression', _noGlobalThis: true }
|
2739
|
+
]
|
2740
|
+
}
|
2741
|
+
]
|
2742
|
+
});
|
2789
2743
|
|
2790
2744
|
// bad hack for undefined and null working without additional logic
|
2791
2745
|
const DEFAULT_VALUE = () => ({
|
@@ -2907,8 +2861,7 @@ const brTable = (input, bc, returns) => {
|
|
2907
2861
|
for (let i = offset; i <= max; i++) {
|
2908
2862
|
// if branch for this num, go to that block
|
2909
2863
|
if (bc[i]) {
|
2910
|
-
table.push(br);
|
2911
|
-
br++;
|
2864
|
+
table.push(br++);
|
2912
2865
|
continue;
|
2913
2866
|
}
|
2914
2867
|
|
@@ -2945,9 +2898,6 @@ const brTable = (input, bc, returns) => {
|
|
2945
2898
|
return out;
|
2946
2899
|
};
|
2947
2900
|
|
2948
|
-
let typeswitchDepth = 0;
|
2949
|
-
|
2950
|
-
let usedTypes = new Set();
|
2951
2901
|
const typeUsed = (scope, x) => {
|
2952
2902
|
if (x == null) return;
|
2953
2903
|
usedTypes.add(x);
|
@@ -3103,7 +3053,7 @@ const typeIsNotOneOf = (type, types, valtype = Valtype.i32) => {
|
|
3103
3053
|
return out;
|
3104
3054
|
};
|
3105
3055
|
|
3106
|
-
const allocVar = (scope, name, global = false, type = true, redecl = false) => {
|
3056
|
+
const allocVar = (scope, name, global = false, type = true, redecl = false, i32 = false) => {
|
3107
3057
|
const target = global ? globals : scope.locals;
|
3108
3058
|
|
3109
3059
|
// already declared
|
@@ -3118,7 +3068,7 @@ const allocVar = (scope, name, global = false, type = true, redecl = false) => {
|
|
3118
3068
|
}
|
3119
3069
|
|
3120
3070
|
let idx = global ? globals['#ind']++ : scope.localInd++;
|
3121
|
-
target[name] = { idx, type: valtypeBinary };
|
3071
|
+
target[name] = { idx, type: i32 ? Valtype.i32 : valtypeBinary };
|
3122
3072
|
|
3123
3073
|
if (type) {
|
3124
3074
|
let typeIdx = global ? globals['#ind']++ : scope.localInd++;
|
@@ -3600,7 +3550,6 @@ const memberTmpNames = scope => {
|
|
3600
3550
|
};
|
3601
3551
|
|
3602
3552
|
// COCTC: cross-object compile-time cache
|
3603
|
-
let coctc = new Map();
|
3604
3553
|
const coctcOffset = prop => {
|
3605
3554
|
if (typeof prop === 'object') {
|
3606
3555
|
if (
|
@@ -4427,7 +4376,6 @@ const generateConditional = (scope, decl) => {
|
|
4427
4376
|
return out;
|
4428
4377
|
};
|
4429
4378
|
|
4430
|
-
let depth = [];
|
4431
4379
|
const generateFor = (scope, decl) => {
|
4432
4380
|
const out = [];
|
4433
4381
|
|
@@ -4903,7 +4851,7 @@ const generateForIn = (scope, decl) => {
|
|
4903
4851
|
|
4904
4852
|
// get length
|
4905
4853
|
[ Opcodes.local_get, pointer ],
|
4906
|
-
[ Opcodes.
|
4854
|
+
[ Opcodes.i32_load16_u, 0, 0 ],
|
4907
4855
|
[ Opcodes.local_tee, length ],
|
4908
4856
|
|
4909
4857
|
[ Opcodes.if, Blocktype.void ]
|
@@ -4936,7 +4884,7 @@ const generateForIn = (scope, decl) => {
|
|
4936
4884
|
|
4937
4885
|
// read key
|
4938
4886
|
[ Opcodes.local_get, pointer ],
|
4939
|
-
[ Opcodes.i32_load, 0,
|
4887
|
+
[ Opcodes.i32_load, 0, 12 ],
|
4940
4888
|
[ Opcodes.local_tee, tmp ],
|
4941
4889
|
|
4942
4890
|
...setType(scope, tmpName, [
|
@@ -4968,7 +4916,7 @@ const generateForIn = (scope, decl) => {
|
|
4968
4916
|
// todo/perf: do not read key for non-enumerables
|
4969
4917
|
// only run body if entry is enumerable
|
4970
4918
|
[ Opcodes.local_get, pointer ],
|
4971
|
-
[ Opcodes.i32_load8_u, 0,
|
4919
|
+
[ Opcodes.i32_load8_u, 0, 24 ],
|
4972
4920
|
[ Opcodes.i32_const, 0b0100 ],
|
4973
4921
|
[ Opcodes.i32_and ],
|
4974
4922
|
[ Opcodes.if, Blocktype.void ],
|
@@ -4976,9 +4924,9 @@ const generateForIn = (scope, decl) => {
|
|
4976
4924
|
[ Opcodes.drop ],
|
4977
4925
|
[ Opcodes.end ],
|
4978
4926
|
|
4979
|
-
// increment pointer by
|
4927
|
+
// increment pointer by 18
|
4980
4928
|
[ Opcodes.local_get, pointer ],
|
4981
|
-
number(
|
4929
|
+
number(18, Valtype.i32),
|
4982
4930
|
[ Opcodes.i32_add ],
|
4983
4931
|
[ Opcodes.local_set, pointer ],
|
4984
4932
|
|
@@ -5364,9 +5312,6 @@ const generateMeta = (scope, decl) => {
|
|
5364
5312
|
return todo(scope, `meta property object ${decl.meta.name} is not supported yet`, true);
|
5365
5313
|
};
|
5366
5314
|
|
5367
|
-
let pages = new Map();
|
5368
|
-
let data = [];
|
5369
|
-
|
5370
5315
|
const compileBytes = (val, itemType) => {
|
5371
5316
|
switch (itemType) {
|
5372
5317
|
case 'i8': return [ val % 256 ];
|
@@ -5805,60 +5750,6 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
5805
5750
|
if (known == null) extraBC = bc;
|
5806
5751
|
}
|
5807
5752
|
|
5808
|
-
if (decl.property.name === '__proto__') {
|
5809
|
-
// todo: support optional
|
5810
|
-
const bc = {};
|
5811
|
-
const prototypes = Object.keys(builtinVars).filter(x => x.endsWith('_prototype'));
|
5812
|
-
|
5813
|
-
const known = knownType(scope, getNodeType(scope, decl.object));
|
5814
|
-
for (const x of prototypes) {
|
5815
|
-
let type = TYPES[x.split('_prototype')[0].slice(2).toLowerCase()];
|
5816
|
-
if (type == null) continue;
|
5817
|
-
|
5818
|
-
// do not __proto__ primitive hack for objects or functions
|
5819
|
-
if (type === TYPES.object || type === TYPES.function) continue;
|
5820
|
-
|
5821
|
-
// hack: do not support primitives for Object.prototype.isPrototypeOf
|
5822
|
-
if (scope.name === '__Object_prototype_isPrototypeOf') {
|
5823
|
-
switch (type) {
|
5824
|
-
case TYPES.boolean:
|
5825
|
-
type = TYPES.booleanobject;
|
5826
|
-
break;
|
5827
|
-
|
5828
|
-
case TYPES.number:
|
5829
|
-
type = TYPES.numberobject;
|
5830
|
-
break;
|
5831
|
-
|
5832
|
-
case TYPES.string:
|
5833
|
-
type = TYPES.stringobject;
|
5834
|
-
break;
|
5835
|
-
|
5836
|
-
case TYPES.bytestring:
|
5837
|
-
continue;
|
5838
|
-
}
|
5839
|
-
}
|
5840
|
-
|
5841
|
-
const ident = {
|
5842
|
-
type: 'Identifier',
|
5843
|
-
name: x
|
5844
|
-
};
|
5845
|
-
|
5846
|
-
// hack: bytestrings should return string prototype
|
5847
|
-
if (type === TYPES.bytestring) ident.name = '__String_prototype';
|
5848
|
-
|
5849
|
-
bc[type] = () => [
|
5850
|
-
...generate(scope, ident),
|
5851
|
-
...setLastType(scope, getNodeType(scope, ident))
|
5852
|
-
];
|
5853
|
-
if (type === known) return bc[type]();
|
5854
|
-
}
|
5855
|
-
|
5856
|
-
if (known == null) {
|
5857
|
-
aliasPrimObjsBC(bc);
|
5858
|
-
extraBC = bc;
|
5859
|
-
}
|
5860
|
-
}
|
5861
|
-
|
5862
5753
|
const useCoctc = Prefs.coctc && coctcOffset(decl) > 0;
|
5863
5754
|
const coctcObjTmp = useCoctc && localTmp(scope, '#coctc_obj' + uniqId(), Valtype.i32);
|
5864
5755
|
|
@@ -6028,7 +5919,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
6028
5919
|
}),
|
6029
5920
|
} : {}),
|
6030
5921
|
|
6031
|
-
[TYPES.undefined]: internalThrow(scope, 'TypeError',
|
5922
|
+
[TYPES.undefined]: internalThrow(scope, 'TypeError', `Cannot read property of undefined`, true),
|
6032
5923
|
|
6033
5924
|
// default: internalThrow(scope, 'TypeError', 'Unsupported member expression object', true)
|
6034
5925
|
default: () => [
|
@@ -6183,10 +6074,25 @@ const generateClass = (scope, decl) => {
|
|
6183
6074
|
// class Foo {}
|
6184
6075
|
// class Bar extends Foo {}
|
6185
6076
|
// Bar.__proto__ = Foo
|
6186
|
-
|
6187
|
-
|
6077
|
+
...generate(scope, {
|
6078
|
+
type: 'CallExpression',
|
6079
|
+
callee: { type: 'Identifier', name: '__Porffor_object_setPrototype' },
|
6080
|
+
arguments: [
|
6081
|
+
root,
|
6082
|
+
decl.superClass
|
6083
|
+
]
|
6084
|
+
}),
|
6188
6085
|
[ Opcodes.drop ],
|
6189
|
-
|
6086
|
+
|
6087
|
+
// Bar.prototype.__proto__ = Foo.prototype
|
6088
|
+
...generate(scope, {
|
6089
|
+
type: 'CallExpression',
|
6090
|
+
callee: { type: 'Identifier', name: '__Porffor_object_setPrototype' },
|
6091
|
+
arguments: [
|
6092
|
+
proto,
|
6093
|
+
getObjProp(decl.superClass, 'prototype')
|
6094
|
+
]
|
6095
|
+
}),
|
6190
6096
|
[ Opcodes.drop ]
|
6191
6097
|
);
|
6192
6098
|
}
|
@@ -6220,18 +6126,6 @@ const generateClass = (scope, decl) => {
|
|
6220
6126
|
// default value to undefined
|
6221
6127
|
value ??= DEFAULT_VALUE();
|
6222
6128
|
|
6223
|
-
let outArr = out, outOp = 'push', outScope = scope;
|
6224
|
-
if (type === 'PropertyDefinition' && !_static) {
|
6225
|
-
// define in construction instead
|
6226
|
-
outArr = func.wasm;
|
6227
|
-
outOp = 'unshift';
|
6228
|
-
object = {
|
6229
|
-
type: 'ThisExpression',
|
6230
|
-
_noGlobalThis: true
|
6231
|
-
};
|
6232
|
-
outScope = func;
|
6233
|
-
}
|
6234
|
-
|
6235
6129
|
if (isFuncType(value.type)) {
|
6236
6130
|
let id = value.id;
|
6237
6131
|
|
@@ -6249,19 +6143,60 @@ const generateClass = (scope, decl) => {
|
|
6249
6143
|
};
|
6250
6144
|
}
|
6251
6145
|
|
6252
|
-
|
6253
|
-
|
6254
|
-
|
6255
|
-
|
6146
|
+
if (type === 'PropertyDefinition' && !_static) {
|
6147
|
+
// define in construction instead
|
6148
|
+
object = {
|
6149
|
+
type: 'ThisExpression',
|
6150
|
+
_noGlobalThis: true
|
6151
|
+
};
|
6256
6152
|
|
6257
|
-
|
6153
|
+
let computedTmp;
|
6154
|
+
if (computed) {
|
6155
|
+
// compute now, reference in construction
|
6156
|
+
computedTmp = allocVar(scope, `#class_computed_prop${uniqId()}`, true, true, false, true);
|
6258
6157
|
|
6259
|
-
|
6260
|
-
|
6261
|
-
|
6158
|
+
out.push(
|
6159
|
+
...toPropertyKey(scope, generate(scope, k), getNodeType(scope, k), computed, true),
|
6160
|
+
[ Opcodes.global_set, computedTmp + 1 ],
|
6161
|
+
[ Opcodes.global_set, computedTmp ]
|
6162
|
+
);
|
6163
|
+
}
|
6262
6164
|
|
6263
|
-
|
6264
|
-
|
6165
|
+
func.wasm.unshift(
|
6166
|
+
...generate(func, object),
|
6167
|
+
Opcodes.i32_to_u,
|
6168
|
+
...getNodeType(func, object),
|
6169
|
+
|
6170
|
+
...(computed ? [
|
6171
|
+
[ Opcodes.global_get, computedTmp ],
|
6172
|
+
[ Opcodes.global_get, computedTmp + 1 ],
|
6173
|
+
] : [
|
6174
|
+
...generate(func, k),
|
6175
|
+
Opcodes.i32_to_u,
|
6176
|
+
...getNodeType(func, k)
|
6177
|
+
]),
|
6178
|
+
|
6179
|
+
...generate(func, value),
|
6180
|
+
...(initKind !== 'value' && initKind !== 'method' ? [ Opcodes.i32_to_u ] : []),
|
6181
|
+
...getNodeType(func, value),
|
6182
|
+
|
6183
|
+
[ Opcodes.call, includeBuiltin(func, `__Porffor_object_class_${initKind}`).index ]
|
6184
|
+
);
|
6185
|
+
} else {
|
6186
|
+
out.push(
|
6187
|
+
...generate(scope, object),
|
6188
|
+
Opcodes.i32_to_u,
|
6189
|
+
...getNodeType(scope, object),
|
6190
|
+
|
6191
|
+
...toPropertyKey(scope, generate(scope, k), getNodeType(scope, k), computed, true),
|
6192
|
+
|
6193
|
+
...generate(scope, value),
|
6194
|
+
...(initKind !== 'value' && initKind !== 'method' ? [ Opcodes.i32_to_u ] : []),
|
6195
|
+
...getNodeType(scope, value),
|
6196
|
+
|
6197
|
+
[ Opcodes.call, includeBuiltin(scope, `__Porffor_object_class_${initKind}`).index ]
|
6198
|
+
);
|
6199
|
+
}
|
6265
6200
|
}
|
6266
6201
|
|
6267
6202
|
delete scope.overrideThis;
|
@@ -6344,7 +6279,7 @@ const generateTaggedTemplate = (scope, decl, global = false, name = undefined, v
|
|
6344
6279
|
return funcIndex[x];
|
6345
6280
|
}
|
6346
6281
|
|
6347
|
-
return scope.locals[x]?.idx ?? globals[x].
|
6282
|
+
return scope.locals[x]?.idx ?? globals[x]?.idx ?? (log.warning('codegen', `unknown immediate in Porffor.wasm: ${x}`) || 0);
|
6348
6283
|
}
|
6349
6284
|
|
6350
6285
|
return n;
|
@@ -6418,7 +6353,6 @@ const objectHack = node => {
|
|
6418
6353
|
|
6419
6354
|
// hack: block these properties as they can be accessed on functions
|
6420
6355
|
if (node.object.name !== 'Porffor' && (node.property.name === 'length' || node.property.name === 'name' || node.property.name === 'call')) return abortOut;
|
6421
|
-
|
6422
6356
|
if (node.property.name === '__proto__') return abortOut;
|
6423
6357
|
|
6424
6358
|
let objectName = node.object.name;
|
@@ -6784,7 +6718,6 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6784
6718
|
return [ func, out ];
|
6785
6719
|
};
|
6786
6720
|
|
6787
|
-
let largestBlockBody = 0;
|
6788
6721
|
const generateBlock = (scope, decl) => {
|
6789
6722
|
let out = [];
|
6790
6723
|
|
@@ -6792,10 +6725,8 @@ const generateBlock = (scope, decl) => {
|
|
6792
6725
|
scope.inferTree.push(decl);
|
6793
6726
|
|
6794
6727
|
let len = decl.body.length, j = 0;
|
6795
|
-
if (len > largestBlockBody) largestBlockBody = len;
|
6796
6728
|
for (let i = 0; i < len; i++) {
|
6797
6729
|
const x = decl.body[i];
|
6798
|
-
if (len >= largestBlockBody) globalThis.progress?.(`${i}/${len}`);
|
6799
6730
|
if (isEmptyNode(x)) continue;
|
6800
6731
|
|
6801
6732
|
if (j++ > 0) out.push([ Opcodes.drop ]);
|
@@ -6958,10 +6889,9 @@ const internalConstrs = {
|
|
6958
6889
|
}
|
6959
6890
|
};
|
6960
6891
|
|
6892
|
+
let globals, tags, exceptions, funcs, indirectFuncs, funcIndex, currentFuncIndex, depth, pages, data, typeswitchDepth, usedTypes, coctc, globalInfer, builtinFuncs, builtinVars, prototypeFuncs;
|
6961
6893
|
export default program => {
|
6962
|
-
globals = {
|
6963
|
-
['#ind']: 0
|
6964
|
-
};
|
6894
|
+
globals = { ['#ind']: 0 };
|
6965
6895
|
tags = [];
|
6966
6896
|
exceptions = [];
|
6967
6897
|
funcs = []; indirectFuncs = [];
|
@@ -6971,26 +6901,22 @@ export default program => {
|
|
6971
6901
|
data = [];
|
6972
6902
|
currentFuncIndex = importedFuncs.length;
|
6973
6903
|
typeswitchDepth = 0;
|
6974
|
-
largestBlockBody = 0;
|
6975
6904
|
usedTypes = new Set([ TYPES.empty, TYPES.undefined, TYPES.number, TYPES.boolean, TYPES.function ]);
|
6976
6905
|
coctc = new Map();
|
6977
6906
|
globalInfer = new Map();
|
6978
6907
|
|
6979
|
-
const valtypeInd = ['i32', 'i64', 'f64'].indexOf(valtype);
|
6980
|
-
|
6981
6908
|
// set generic opcodes for current valtype
|
6909
|
+
const valtypeInd = ['i32', 'i64', 'f64'].indexOf(valtype);
|
6982
6910
|
Opcodes.const = [ Opcodes.i32_const, Opcodes.i64_const, Opcodes.f64_const ][valtypeInd];
|
6983
6911
|
Opcodes.eq = [ Opcodes.i32_eq, Opcodes.i64_eq, Opcodes.f64_eq ][valtypeInd];
|
6984
6912
|
Opcodes.eqz = [ [ [ Opcodes.i32_eqz ] ], [ [ Opcodes.i64_eqz ] ], [ number(0), [ Opcodes.f64_eq ] ] ][valtypeInd];
|
6985
6913
|
Opcodes.mul = [ Opcodes.i32_mul, Opcodes.i64_mul, Opcodes.f64_mul ][valtypeInd];
|
6986
6914
|
Opcodes.add = [ Opcodes.i32_add, Opcodes.i64_add, Opcodes.f64_add ][valtypeInd];
|
6987
6915
|
Opcodes.sub = [ Opcodes.i32_sub, Opcodes.i64_sub, Opcodes.f64_sub ][valtypeInd];
|
6988
|
-
|
6989
6916
|
Opcodes.i32_to = [ [], [ Opcodes.i32_wrap_i64 ], Opcodes.i32_trunc_sat_f64_s ][valtypeInd];
|
6990
6917
|
Opcodes.i32_to_u = [ [], [ Opcodes.i32_wrap_i64 ], Opcodes.i32_trunc_sat_f64_u ][valtypeInd];
|
6991
6918
|
Opcodes.i32_from = [ [], [ Opcodes.i64_extend_i32_s ], [ Opcodes.f64_convert_i32_s ] ][valtypeInd];
|
6992
6919
|
Opcodes.i32_from_u = [ [], [ Opcodes.i64_extend_i32_u ], [ Opcodes.f64_convert_i32_u ] ][valtypeInd];
|
6993
|
-
|
6994
6920
|
Opcodes.load = [ Opcodes.i32_load, Opcodes.i64_load, Opcodes.f64_load ][valtypeInd];
|
6995
6921
|
Opcodes.store = [ Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store ][valtypeInd];
|
6996
6922
|
|
package/compiler/precompile.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Opcodes, Valtype } from './wasmSpec.js';
|
2
2
|
import { read_signedLEB128, read_unsignedLEB128 } from './encoding.js';
|
3
|
-
import { TYPES } from './types.js';
|
3
|
+
import { TYPES, TYPE_NAMES } from './types.js';
|
4
4
|
import { log } from './log.js';
|
5
5
|
|
6
6
|
import process from 'node:process';
|
@@ -41,7 +41,7 @@ const compile = async (file, _funcs) => {
|
|
41
41
|
let first = source.slice(0, source.indexOf('\n'));
|
42
42
|
|
43
43
|
if (first.startsWith('export default')) {
|
44
|
-
source = await (await import('file://' + file)).default();
|
44
|
+
source = await (await import('file://' + file)).default({ TYPES, TYPE_NAMES });
|
45
45
|
first = source.slice(0, source.indexOf('\n'));
|
46
46
|
}
|
47
47
|
|
@@ -155,11 +155,10 @@ const compile = async (file, _funcs) => {
|
|
155
155
|
}
|
156
156
|
|
157
157
|
if (n[0] === Opcodes.throw) {
|
158
|
-
if (!bodyHasTopLevelThrow && depth === 0) log.warning('codegen', `top-level throw in ${x.name}`);
|
159
|
-
|
160
158
|
x.usesTag = true;
|
159
|
+
let id;
|
161
160
|
if (y[0] === Opcodes.i32_const && n[1] === 0) {
|
162
|
-
|
161
|
+
id = read_signedLEB128(y.slice(1));
|
163
162
|
y.splice(0, 10, 'throw', exceptions[id].constructor, exceptions[id].message);
|
164
163
|
|
165
164
|
// remove throw inst
|
@@ -167,6 +166,8 @@ const compile = async (file, _funcs) => {
|
|
167
166
|
} else {
|
168
167
|
n[1]--;
|
169
168
|
}
|
169
|
+
|
170
|
+
if (!bodyHasTopLevelThrow && depth === 0) log.warning('codegen', `top-level throw in ${x.name} (${exceptions[id].constructor}: ${exceptions[id].message})`);
|
170
171
|
}
|
171
172
|
|
172
173
|
if (n[0] === Opcodes.catch) {
|