porffor 0.2.0-767de65 → 0.2.0-80c08d4
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/CONTRIBUTING.md +248 -0
- package/README.md +71 -44
- package/asur/index.js +2 -2
- package/compiler/assemble.js +2 -2
- package/compiler/builtins/annexb_string.js +1 -1
- package/compiler/builtins/annexb_string.ts +1 -2
- package/compiler/builtins/array.ts +1 -1
- package/compiler/builtins/base64.ts +4 -79
- package/compiler/builtins/crypto.ts +1 -1
- package/compiler/builtins/date.ts +2071 -0
- package/compiler/builtins/escape.ts +1 -1
- package/compiler/builtins/int.ts +1 -1
- package/compiler/builtins/number.ts +1 -1
- package/compiler/builtins/porffor.d.ts +21 -4
- package/compiler/builtins/string.ts +1 -1
- package/compiler/builtins/tostring.ts +1 -1
- package/compiler/builtins.js +12 -26
- package/compiler/codegen.js +165 -59
- package/compiler/decompile.js +0 -1
- package/compiler/generated_builtins.js +855 -69
- package/compiler/parse.js +4 -2
- package/compiler/precompile.js +7 -2
- package/compiler/prefs.js +6 -5
- package/compiler/wasmSpec.js +1 -0
- package/compiler/wrap.js +8 -5
- package/package.json +1 -1
- package/rhemyn/compile.js +42 -25
- package/rhemyn/parse.js +4 -5
- package/runner/index.js +45 -4
- package/runner/repl.js +2 -2
- package/runner/sizes.js +1 -1
- package/.vscode/launch.json +0 -18
- package/empty.js +0 -0
- package/hello.js +0 -2
- package/test262_changes_from_1afe9b87d2_to_04-09.md +0 -270
package/compiler/builtins/int.ts
CHANGED
@@ -7,23 +7,40 @@ type PorfforGlobal = {
|
|
7
7
|
wasm: {
|
8
8
|
(...args: any[]): any;
|
9
9
|
i32: {
|
10
|
-
or(a: i32, b: i32): i32;
|
11
|
-
|
12
10
|
load(pointer: i32, align: i32, offset: i32): i32;
|
13
11
|
store(pointer: i32, value: i32, align: i32, offset: i32): i32;
|
14
12
|
load8_u(pointer: i32, align: i32, offset: i32): i32;
|
15
13
|
store8(pointer: i32, value: i32, align: i32, offset: i32): i32;
|
16
14
|
load16_u(pointer: i32, align: i32, offset: i32): i32;
|
17
15
|
store16(pointer: i32, value: i32, align: i32, offset: i32): i32;
|
16
|
+
const(value: i32): i32;
|
17
|
+
}
|
18
|
+
|
19
|
+
f64: {
|
20
|
+
load(pointer: i32, align: i32, offset: i32): i32;
|
21
|
+
store(pointer: i32, value: f64, align: i32, offset: i32): f64;
|
18
22
|
}
|
19
23
|
}
|
20
24
|
|
21
|
-
// randomInt(): i32;
|
22
25
|
randomByte(): i32;
|
23
26
|
|
24
27
|
type(x: any): bytestring;
|
25
28
|
rawType(x: any): i32;
|
26
|
-
TYPES:
|
29
|
+
TYPES: {
|
30
|
+
number: i32;
|
31
|
+
boolean: i32;
|
32
|
+
string: i32;
|
33
|
+
undefined: i32;
|
34
|
+
object: i32;
|
35
|
+
function: i32;
|
36
|
+
symbol: i32;
|
37
|
+
bigint: i32;
|
38
|
+
|
39
|
+
_array: i32;
|
40
|
+
_regexp: i32;
|
41
|
+
_bytestring: i32;
|
42
|
+
_date: i32;
|
43
|
+
}
|
27
44
|
|
28
45
|
fastOr(...args: any): boolean;
|
29
46
|
fastAnd(...args: any): boolean;
|
package/compiler/builtins.js
CHANGED
@@ -23,6 +23,12 @@ export const importedFuncs = [
|
|
23
23
|
params: 0,
|
24
24
|
returns: 1
|
25
25
|
},
|
26
|
+
{
|
27
|
+
name: 'timeOrigin',
|
28
|
+
import: 'u',
|
29
|
+
params: 0,
|
30
|
+
returns: 1
|
31
|
+
},
|
26
32
|
{
|
27
33
|
name: 'profile1',
|
28
34
|
import: 'y',
|
@@ -140,6 +146,10 @@ export const BuiltinVars = function() {
|
|
140
146
|
for (const x in TYPES) {
|
141
147
|
this['__Porffor_TYPES_' + x] = number(TYPES[x]);
|
142
148
|
}
|
149
|
+
|
150
|
+
this.__performance_timeOrigin = [
|
151
|
+
[ Opcodes.call, importedFuncs.timeOrigin ]
|
152
|
+
];
|
143
153
|
};
|
144
154
|
|
145
155
|
export const BuiltinFuncs = function() {
|
@@ -206,7 +216,7 @@ export const BuiltinFuncs = function() {
|
|
206
216
|
};
|
207
217
|
|
208
218
|
|
209
|
-
this.
|
219
|
+
this.__Porffor_print = {
|
210
220
|
params: [ valtypeBinary, Valtype.i32 ],
|
211
221
|
typedParams: true,
|
212
222
|
locals: [ Valtype.i32, Valtype.i32 ],
|
@@ -358,10 +368,7 @@ export const BuiltinFuncs = function() {
|
|
358
368
|
[ Opcodes.local_get, 0 ],
|
359
369
|
[ Opcodes.call, importedFuncs.print ],
|
360
370
|
]
|
361
|
-
}, Blocktype.void)
|
362
|
-
|
363
|
-
...char('\n'),
|
364
|
-
[ Opcodes.call, importedFuncs.printChar ]
|
371
|
+
}, Blocktype.void)
|
365
372
|
]
|
366
373
|
};
|
367
374
|
|
@@ -908,27 +915,6 @@ export const BuiltinFuncs = function() {
|
|
908
915
|
]
|
909
916
|
};
|
910
917
|
|
911
|
-
// this.__Porffor_randomInt = {
|
912
|
-
// params: [],
|
913
|
-
// locals: prng.locals,
|
914
|
-
// localNames: [ 's1', 's0' ],
|
915
|
-
// globals: prng.globals,
|
916
|
-
// globalNames: [ 'state0', 'state1' ],
|
917
|
-
// globalInits: [ prngSeed0, prngSeed1 ],
|
918
|
-
// returns: [ Valtype.i32 ],
|
919
|
-
// wasm: [
|
920
|
-
// ...prng.wasm,
|
921
|
-
|
922
|
-
// ...(prng.returns === Valtype.i64 ? [
|
923
|
-
// // the lowest bits of the output generated by xorshift128+ have low quality
|
924
|
-
// ...number(56, Valtype.i64),
|
925
|
-
// [ Opcodes.i64_shr_u ],
|
926
|
-
|
927
|
-
// [ Opcodes.i32_wrap_i64 ],
|
928
|
-
// ] : []),
|
929
|
-
// ]
|
930
|
-
// };
|
931
|
-
|
932
918
|
this.__Porffor_randomByte = {
|
933
919
|
params: [],
|
934
920
|
locals: prng.locals,
|
package/compiler/codegen.js
CHANGED
@@ -201,7 +201,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
201
201
|
}
|
202
202
|
|
203
203
|
let inst = Opcodes[asm[0].replace('.', '_')];
|
204
|
-
if (
|
204
|
+
if (inst == null) throw new Error(`inline asm: inst ${asm[0]} not found`);
|
205
205
|
|
206
206
|
if (!Array.isArray(inst)) inst = [ inst ];
|
207
207
|
const immediates = asm.slice(1).map(x => {
|
@@ -210,7 +210,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
210
210
|
return int;
|
211
211
|
});
|
212
212
|
|
213
|
-
out.push([ ...inst, ...immediates ]);
|
213
|
+
out.push([ ...inst, ...immediates.flatMap(x => signedLEB128(x)) ]);
|
214
214
|
}
|
215
215
|
|
216
216
|
return out;
|
@@ -460,7 +460,7 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
460
460
|
const rightLength = localTmp(scope, 'concat_right_length', Valtype.i32);
|
461
461
|
const leftLength = localTmp(scope, 'concat_left_length', Valtype.i32);
|
462
462
|
|
463
|
-
if (assign) {
|
463
|
+
if (assign && Prefs.aotPointerOpt) {
|
464
464
|
const pointer = scope.arrays?.get(name ?? '$undeclared');
|
465
465
|
|
466
466
|
return [
|
@@ -1273,6 +1273,18 @@ const getNodeType = (scope, node) => {
|
|
1273
1273
|
return TYPES.number;
|
1274
1274
|
}
|
1275
1275
|
|
1276
|
+
if (node.type === 'NewExpression' && builtinFuncs[name + '$constructor']) {
|
1277
|
+
if (builtinFuncs[name + '$constructor'].typedReturns) {
|
1278
|
+
if (scope.locals['#last_type']) return getLastType(scope);
|
1279
|
+
|
1280
|
+
// presume
|
1281
|
+
// todo: warn here?
|
1282
|
+
return TYPES.number;
|
1283
|
+
}
|
1284
|
+
|
1285
|
+
return builtinFuncs[name + '$constructor'].returnType ?? TYPES.number;
|
1286
|
+
}
|
1287
|
+
|
1276
1288
|
const func = funcs.find(x => x.name === name);
|
1277
1289
|
|
1278
1290
|
if (func) {
|
@@ -1460,16 +1472,23 @@ const countLeftover = wasm => {
|
|
1460
1472
|
if (depth === 0)
|
1461
1473
|
if ([Opcodes.throw, Opcodes.drop, Opcodes.local_set, Opcodes.global_set].includes(inst[0])) count--;
|
1462
1474
|
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] < 0x0a)) {}
|
1463
|
-
else if ([Opcodes.local_get, Opcodes.global_get, Opcodes.f64_const, Opcodes.i32_const, Opcodes.i64_const, Opcodes.v128_const].includes(inst[0])) count++;
|
1475
|
+
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++;
|
1464
1476
|
else if ([Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store, Opcodes.i32_store16, Opcodes.i32_store8].includes(inst[0])) count -= 2;
|
1465
1477
|
else if (Opcodes.memory_copy[0] === inst[0] && Opcodes.memory_copy[1] === inst[1]) count -= 3;
|
1466
1478
|
else if (inst[0] === Opcodes.return) count = 0;
|
1467
1479
|
else if (inst[0] === Opcodes.call) {
|
1468
1480
|
let func = funcs.find(x => x.index === inst[1]);
|
1469
|
-
if (
|
1470
|
-
count
|
1471
|
-
} else
|
1472
|
-
|
1481
|
+
if (inst[1] === -1) {
|
1482
|
+
// todo: count for calling self
|
1483
|
+
} else if (!func && inst[1] < importedFuncs.length) {
|
1484
|
+
count -= importedFuncs[inst[1]].params;
|
1485
|
+
count += importedFuncs[inst[1]].returns;
|
1486
|
+
} else {
|
1487
|
+
if (func) {
|
1488
|
+
count -= func.params.length;
|
1489
|
+
} else count--;
|
1490
|
+
if (func) count += func.returns.length;
|
1491
|
+
}
|
1473
1492
|
} else count--;
|
1474
1493
|
|
1475
1494
|
// console.log(count, decompile([ inst ]).slice(0, -1));
|
@@ -1627,18 +1646,25 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1627
1646
|
// megahack for /regex/.func()
|
1628
1647
|
const funcName = decl.callee.property.name;
|
1629
1648
|
if (decl.callee.object.regex && Object.hasOwn(Rhemyn, funcName)) {
|
1630
|
-
const
|
1649
|
+
const regex = decl.callee.object.regex.pattern;
|
1650
|
+
const rhemynName = `regex_${funcName}_${regex}`;
|
1631
1651
|
|
1632
|
-
funcIndex[
|
1633
|
-
|
1652
|
+
if (!funcIndex[rhemynName]) {
|
1653
|
+
const func = Rhemyn[funcName](regex, currentFuncIndex++, rhemynName);
|
1654
|
+
|
1655
|
+
funcIndex[func.name] = func.index;
|
1656
|
+
funcs.push(func);
|
1657
|
+
}
|
1634
1658
|
|
1659
|
+
const idx = funcIndex[rhemynName];
|
1635
1660
|
return [
|
1636
1661
|
// make string arg
|
1637
1662
|
...generate(scope, decl.arguments[0]),
|
1663
|
+
Opcodes.i32_to_u,
|
1664
|
+
...getNodeType(scope, decl.arguments[0]),
|
1638
1665
|
|
1639
1666
|
// call regex func
|
1640
|
-
Opcodes.
|
1641
|
-
[ Opcodes.call, func.index ],
|
1667
|
+
[ Opcodes.call, idx ],
|
1642
1668
|
Opcodes.i32_from_u,
|
1643
1669
|
|
1644
1670
|
...number(TYPES.boolean, Valtype.i32),
|
@@ -1678,6 +1704,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1678
1704
|
|
1679
1705
|
protoBC[type] = generateCall(scope, {
|
1680
1706
|
callee: {
|
1707
|
+
type: 'Identifier',
|
1681
1708
|
name: x
|
1682
1709
|
},
|
1683
1710
|
arguments: [ target, ...decl.arguments ],
|
@@ -1800,20 +1827,20 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1800
1827
|
idx = funcIndex[name];
|
1801
1828
|
|
1802
1829
|
// infer arguments types from builtins params
|
1803
|
-
const func = funcs.find(x => x.name === name);
|
1804
|
-
for (let i = 0; i < decl.arguments.length; i++) {
|
1805
|
-
|
1806
|
-
|
1807
|
-
|
1808
|
-
|
1809
|
-
|
1810
|
-
|
1811
|
-
|
1812
|
-
|
1813
|
-
|
1814
|
-
|
1815
|
-
|
1816
|
-
}
|
1830
|
+
// const func = funcs.find(x => x.name === name);
|
1831
|
+
// for (let i = 0; i < decl.arguments.length; i++) {
|
1832
|
+
// const arg = decl.arguments[i];
|
1833
|
+
// if (!arg.name) continue;
|
1834
|
+
|
1835
|
+
// const local = scope.locals[arg.name];
|
1836
|
+
// if (!local) continue;
|
1837
|
+
|
1838
|
+
// local.type = func.params[i];
|
1839
|
+
// if (local.type === Valtype.v128) {
|
1840
|
+
// // specify vec subtype inferred from last vec type in function name
|
1841
|
+
// local.vecType = name.split('_').reverse().find(x => x.includes('x'));
|
1842
|
+
// }
|
1843
|
+
// }
|
1817
1844
|
}
|
1818
1845
|
|
1819
1846
|
if (idx === undefined && internalConstrs[name]) return internalConstrs[name].generate(scope, decl, _global, _name);
|
@@ -1826,28 +1853,25 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1826
1853
|
if (idx === undefined && name.startsWith('__Porffor_wasm_')) {
|
1827
1854
|
const wasmOps = {
|
1828
1855
|
// pointer, align, offset
|
1829
|
-
i32_load: { imms: 2, args:
|
1856
|
+
i32_load: { imms: 2, args: [ true ], returns: 1 },
|
1830
1857
|
// pointer, value, align, offset
|
1831
|
-
i32_store: { imms: 2, args:
|
1858
|
+
i32_store: { imms: 2, args: [ true, true ], returns: 0 },
|
1832
1859
|
// pointer, align, offset
|
1833
|
-
i32_load8_u: { imms: 2, args:
|
1860
|
+
i32_load8_u: { imms: 2, args: [ true ], returns: 1 },
|
1834
1861
|
// pointer, value, align, offset
|
1835
|
-
i32_store8: { imms: 2, args:
|
1862
|
+
i32_store8: { imms: 2, args: [ true, true ], returns: 0 },
|
1836
1863
|
// pointer, align, offset
|
1837
|
-
i32_load16_u: { imms: 2, args:
|
1864
|
+
i32_load16_u: { imms: 2, args: [ true ], returns: 1 },
|
1838
1865
|
// pointer, value, align, offset
|
1839
|
-
i32_store16: { imms: 2, args:
|
1866
|
+
i32_store16: { imms: 2, args: [ true, true ], returns: 0 },
|
1840
1867
|
|
1841
1868
|
// pointer, align, offset
|
1842
|
-
f64_load: { imms: 2, args:
|
1869
|
+
f64_load: { imms: 2, args: [ true ], returns: 0 }, // 0 due to not i32
|
1843
1870
|
// pointer, value, align, offset
|
1844
|
-
f64_store: { imms: 2, args:
|
1871
|
+
f64_store: { imms: 2, args: [ true, false ], returns: 0 },
|
1845
1872
|
|
1846
1873
|
// value
|
1847
|
-
i32_const: { imms: 1, args:
|
1848
|
-
|
1849
|
-
// a, b
|
1850
|
-
i32_or: { imms: 0, args: 2, returns: 1 },
|
1874
|
+
i32_const: { imms: 1, args: [], returns: 1 },
|
1851
1875
|
};
|
1852
1876
|
|
1853
1877
|
const opName = name.slice('__Porffor_wasm_'.length);
|
@@ -1856,13 +1880,13 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1856
1880
|
const op = wasmOps[opName];
|
1857
1881
|
|
1858
1882
|
const argOut = [];
|
1859
|
-
for (let i = 0; i < op.args; i++) argOut.push(
|
1883
|
+
for (let i = 0; i < op.args.length; i++) argOut.push(
|
1860
1884
|
...generate(scope, decl.arguments[i]),
|
1861
|
-
Opcodes.i32_to
|
1885
|
+
...(op.args[i] ? [ Opcodes.i32_to ] : [])
|
1862
1886
|
);
|
1863
1887
|
|
1864
1888
|
// literals only
|
1865
|
-
const imms = decl.arguments.slice(op.args).map(x => x.value);
|
1889
|
+
const imms = decl.arguments.slice(op.args.length).map(x => x.value);
|
1866
1890
|
|
1867
1891
|
return [
|
1868
1892
|
...argOut,
|
@@ -1937,7 +1961,20 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1937
1961
|
const generateNew = (scope, decl, _global, _name) => {
|
1938
1962
|
// hack: basically treat this as a normal call for builtins for now
|
1939
1963
|
const name = mapName(decl.callee.name);
|
1964
|
+
|
1940
1965
|
if (internalConstrs[name] && !internalConstrs[name].notConstr) return internalConstrs[name].generate(scope, decl, _global, _name);
|
1966
|
+
|
1967
|
+
if (builtinFuncs[name + '$constructor']) {
|
1968
|
+
// custom ...$constructor override builtin func
|
1969
|
+
return generateCall(scope, {
|
1970
|
+
...decl,
|
1971
|
+
callee: {
|
1972
|
+
type: 'Identifier',
|
1973
|
+
name: name + '$constructor'
|
1974
|
+
}
|
1975
|
+
}, _global, _name);
|
1976
|
+
}
|
1977
|
+
|
1941
1978
|
if (!builtinFuncs[name]) return todo(scope, `new statement is not supported yet`); // return todo(scope, `new statement is not supported yet (new ${unhackName(name)})`);
|
1942
1979
|
|
1943
1980
|
return generateCall(scope, decl, _global, _name);
|
@@ -2128,8 +2165,8 @@ const addVarMetadata = (scope, name, global = false, metadata = {}) => {
|
|
2128
2165
|
|
2129
2166
|
const typeAnnoToPorfType = x => {
|
2130
2167
|
if (!x) return null;
|
2131
|
-
if (TYPES[x] != null) return TYPES[x];
|
2132
|
-
if (TYPES['_' + x] != null) return TYPES['_' + x];
|
2168
|
+
if (TYPES[x.toLowerCase()] != null) return TYPES[x.toLowerCase()];
|
2169
|
+
if (TYPES['_' + x.toLowerCase()] != null) return TYPES['_' + x.toLowerCase()];
|
2133
2170
|
|
2134
2171
|
switch (x) {
|
2135
2172
|
case 'i32':
|
@@ -2172,6 +2209,7 @@ const generateVar = (scope, decl) => {
|
|
2172
2209
|
|
2173
2210
|
// global variable if in top scope (main) and var ..., or if wanted
|
2174
2211
|
const global = topLevel || decl._bare; // decl.kind === 'var';
|
2212
|
+
const target = global ? globals : scope.locals;
|
2175
2213
|
|
2176
2214
|
for (const x of decl.declarations) {
|
2177
2215
|
const name = mapName(x.id.name);
|
@@ -2193,17 +2231,29 @@ const generateVar = (scope, decl) => {
|
|
2193
2231
|
continue; // always ignore
|
2194
2232
|
}
|
2195
2233
|
|
2234
|
+
// // generate init before allocating var
|
2235
|
+
// let generated;
|
2236
|
+
// if (x.init) generated = generate(scope, x.init, global, name);
|
2237
|
+
|
2196
2238
|
const typed = typedInput && x.id.typeAnnotation;
|
2197
|
-
let idx = allocVar(scope, name, global, !typed);
|
2239
|
+
let idx = allocVar(scope, name, global, !(typed && extractTypeAnnotation(x.id).type != null));
|
2198
2240
|
|
2199
2241
|
if (typed) {
|
2200
2242
|
addVarMetadata(scope, name, global, extractTypeAnnotation(x.id));
|
2201
2243
|
}
|
2202
2244
|
|
2203
2245
|
if (x.init) {
|
2204
|
-
|
2205
|
-
|
2206
|
-
|
2246
|
+
const generated = generate(scope, x.init, global, name);
|
2247
|
+
if (scope.arrays?.get(name) != null) {
|
2248
|
+
// hack to set local as pointer before
|
2249
|
+
out.push(...number(scope.arrays.get(name)), [ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
|
2250
|
+
if (generated.at(-1) == Opcodes.i32_from_u) generated.pop();
|
2251
|
+
generated.pop();
|
2252
|
+
out = out.concat(generated);
|
2253
|
+
} else {
|
2254
|
+
out = out.concat(generated);
|
2255
|
+
out.push([ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
|
2256
|
+
}
|
2207
2257
|
out.push(...setType(scope, name, getNodeType(scope, x.init)));
|
2208
2258
|
}
|
2209
2259
|
|
@@ -2230,6 +2280,8 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2230
2280
|
return [];
|
2231
2281
|
}
|
2232
2282
|
|
2283
|
+
const op = decl.operator.slice(0, -1) || '=';
|
2284
|
+
|
2233
2285
|
// hack: .length setter
|
2234
2286
|
if (decl.left.type === 'MemberExpression' && decl.left.property.name === 'length') {
|
2235
2287
|
const name = decl.left.object.name;
|
@@ -2238,14 +2290,20 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2238
2290
|
const aotPointer = Prefs.aotPointerOpt && pointer != null;
|
2239
2291
|
|
2240
2292
|
const newValueTmp = localTmp(scope, '__length_setter_tmp');
|
2293
|
+
const pointerTmp = op === '=' ? null : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2241
2294
|
|
2242
2295
|
return [
|
2243
2296
|
...(aotPointer ? number(0, Valtype.i32) : [
|
2244
2297
|
...generate(scope, decl.left.object),
|
2245
2298
|
Opcodes.i32_to_u
|
2246
2299
|
]),
|
2300
|
+
...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2247
2301
|
|
2248
|
-
...generate(scope, decl.right),
|
2302
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2303
|
+
[ Opcodes.local_get, pointerTmp ],
|
2304
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
2305
|
+
Opcodes.i32_from_u
|
2306
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right))),
|
2249
2307
|
[ Opcodes.local_tee, newValueTmp ],
|
2250
2308
|
|
2251
2309
|
Opcodes.i32_to_u,
|
@@ -2255,8 +2313,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2255
2313
|
];
|
2256
2314
|
}
|
2257
2315
|
|
2258
|
-
const op = decl.operator.slice(0, -1) || '=';
|
2259
|
-
|
2260
2316
|
// arr[i]
|
2261
2317
|
if (decl.left.type === 'MemberExpression' && decl.left.computed) {
|
2262
2318
|
const name = decl.left.object.name;
|
@@ -3060,12 +3116,14 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3060
3116
|
// todo: can we just have 1 undeclared array? probably not? but this is not really memory efficient
|
3061
3117
|
const uniqueName = name === '$undeclared' ? name + Math.random().toString().slice(2) : name;
|
3062
3118
|
|
3063
|
-
if (Prefs.scopedPageNames) scope.arrays.set(name, allocPage(scope, `${
|
3119
|
+
if (Prefs.scopedPageNames) scope.arrays.set(name, allocPage(scope, `${getAllocType(itemType)}: ${scope.name}/${uniqueName}`, itemType) * pageSize);
|
3064
3120
|
else scope.arrays.set(name, allocPage(scope, `${getAllocType(itemType)}: ${uniqueName}`, itemType) * pageSize);
|
3065
3121
|
}
|
3066
3122
|
|
3067
3123
|
const pointer = scope.arrays.get(name);
|
3068
3124
|
|
3125
|
+
const local = global ? globals[name] : scope.locals[name];
|
3126
|
+
|
3069
3127
|
const useRawElements = !!decl.rawElements;
|
3070
3128
|
const elements = useRawElements ? decl.rawElements : decl.elements;
|
3071
3129
|
|
@@ -3098,11 +3156,22 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3098
3156
|
return [ out, pointer ];
|
3099
3157
|
}
|
3100
3158
|
|
3159
|
+
const pointerTmp = local != null ? localTmp(scope, '#makearray_pointer_tmp', Valtype.i32) : null;
|
3160
|
+
if (pointerTmp != null) {
|
3161
|
+
out.push(
|
3162
|
+
[ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
3163
|
+
Opcodes.i32_to_u,
|
3164
|
+
[ Opcodes.local_set, pointerTmp ]
|
3165
|
+
);
|
3166
|
+
}
|
3167
|
+
|
3168
|
+
const pointerWasm = pointerTmp != null ? [ [ Opcodes.local_get, pointerTmp ] ] : number(pointer, Valtype.i32);
|
3169
|
+
|
3101
3170
|
// store length as 0th array
|
3102
3171
|
out.push(
|
3103
|
-
...
|
3172
|
+
...pointerWasm,
|
3104
3173
|
...number(length, Valtype.i32),
|
3105
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1,
|
3174
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ]
|
3106
3175
|
);
|
3107
3176
|
|
3108
3177
|
const storeOp = StoreOps[itemType];
|
@@ -3111,14 +3180,14 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3111
3180
|
if (elements[i] == null) continue;
|
3112
3181
|
|
3113
3182
|
out.push(
|
3114
|
-
...
|
3183
|
+
...pointerWasm,
|
3115
3184
|
...(useRawElements ? number(elements[i], Valtype[valtype]) : generate(scope, elements[i])),
|
3116
|
-
[ storeOp, (Math.log2(ValtypeSize[itemType]) || 1) - 1, ...unsignedLEB128(
|
3185
|
+
[ storeOp, (Math.log2(ValtypeSize[itemType]) || 1) - 1, ...unsignedLEB128(ValtypeSize.i32 + i * ValtypeSize[itemType]) ]
|
3117
3186
|
);
|
3118
3187
|
}
|
3119
3188
|
|
3120
3189
|
// local value as pointer
|
3121
|
-
out.push(...
|
3190
|
+
out.push(...pointerWasm, Opcodes.i32_from_u);
|
3122
3191
|
|
3123
3192
|
return [ out, pointer ];
|
3124
3193
|
};
|
@@ -3473,6 +3542,8 @@ const internalConstrs = {
|
|
3473
3542
|
);
|
3474
3543
|
}
|
3475
3544
|
|
3545
|
+
out.push(Opcodes.i32_from_u);
|
3546
|
+
|
3476
3547
|
return out;
|
3477
3548
|
},
|
3478
3549
|
type: TYPES.boolean,
|
@@ -3491,6 +3562,8 @@ const internalConstrs = {
|
|
3491
3562
|
);
|
3492
3563
|
}
|
3493
3564
|
|
3565
|
+
out.push(Opcodes.i32_from_u);
|
3566
|
+
|
3494
3567
|
return out;
|
3495
3568
|
},
|
3496
3569
|
type: TYPES.boolean,
|
@@ -3545,6 +3618,39 @@ const internalConstrs = {
|
|
3545
3618
|
type: TYPES.number,
|
3546
3619
|
notConstr: true,
|
3547
3620
|
length: 2
|
3621
|
+
},
|
3622
|
+
|
3623
|
+
__console_log: {
|
3624
|
+
generate: (scope, decl) => {
|
3625
|
+
const out = [];
|
3626
|
+
|
3627
|
+
for (let i = 0; i < decl.arguments.length; i++) {
|
3628
|
+
out.push(
|
3629
|
+
...generateCall(scope, {
|
3630
|
+
callee: {
|
3631
|
+
type: 'Identifier',
|
3632
|
+
name: '__Porffor_print'
|
3633
|
+
},
|
3634
|
+
arguments: [ decl.arguments[i] ]
|
3635
|
+
}),
|
3636
|
+
|
3637
|
+
// print space
|
3638
|
+
...number(32),
|
3639
|
+
[ Opcodes.call, importedFuncs.printChar ]
|
3640
|
+
);
|
3641
|
+
}
|
3642
|
+
|
3643
|
+
// print newline
|
3644
|
+
out.push(
|
3645
|
+
...number(10),
|
3646
|
+
[ Opcodes.call, importedFuncs.printChar ]
|
3647
|
+
);
|
3648
|
+
|
3649
|
+
return out;
|
3650
|
+
},
|
3651
|
+
type: TYPES.undefined,
|
3652
|
+
notConstr: true,
|
3653
|
+
length: 0
|
3548
3654
|
}
|
3549
3655
|
};
|
3550
3656
|
|
@@ -3579,7 +3685,7 @@ export default program => {
|
|
3579
3685
|
|
3580
3686
|
globalThis.valtype = 'f64';
|
3581
3687
|
|
3582
|
-
const valtypeOpt = process.argv.find(x => x.startsWith('
|
3688
|
+
const valtypeOpt = process.argv.find(x => x.startsWith('--valtype='));
|
3583
3689
|
if (valtypeOpt) valtype = valtypeOpt.split('=')[1];
|
3584
3690
|
|
3585
3691
|
globalThis.valtypeBinary = Valtype[valtype];
|
@@ -3587,7 +3693,7 @@ export default program => {
|
|
3587
3693
|
const valtypeInd = ['i32', 'i64', 'f64'].indexOf(valtype);
|
3588
3694
|
|
3589
3695
|
globalThis.pageSize = PageSize;
|
3590
|
-
const pageSizeOpt = process.argv.find(x => x.startsWith('
|
3696
|
+
const pageSizeOpt = process.argv.find(x => x.startsWith('--page-size='));
|
3591
3697
|
if (pageSizeOpt) pageSize = parseInt(pageSizeOpt.split('=')[1]) * 1024;
|
3592
3698
|
|
3593
3699
|
// set generic opcodes for current valtype
|