porffor 0.16.0-a2e115b05 → 0.16.0-a8f23d010
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 +1 -1
- package/compiler/allocators/chunk.js +0 -0
- package/compiler/allocators/solo.js +0 -0
- package/compiler/allocators/static.js +41 -0
- package/compiler/assemble.js +5 -4
- package/compiler/builtins.js +2 -2
- package/compiler/codegen.js +58 -185
- package/compiler/cyclone.js +535 -0
- package/compiler/decompile.js +3 -1
- package/compiler/havoc.js +93 -0
- package/compiler/index.js +89 -6
- package/compiler/opt.js +4 -40
- package/compiler/parse.js +1 -1
- package/compiler/pgo.js +207 -0
- package/compiler/precompile.js +3 -1
- package/compiler/prefs.js +7 -2
- package/compiler/wrap.js +53 -12
- package/no_pgo.txt +923 -0
- package/package.json +3 -5
- package/pgo.txt +916 -0
- package/runner/index.js +21 -11
- /package/runner/{profiler.js → profile.js} +0 -0
package/CONTRIBUTING.md
CHANGED
@@ -26,7 +26,7 @@ You can also swap out `node` in the alias to use another runtime like Deno (`den
|
|
26
26
|
|
27
27
|
### Precompile
|
28
28
|
|
29
|
-
**If you update any file inside `compiler/builtins` you will need to do this for it to update inside Porffor otherwise your changes will have no effect.** Run
|
29
|
+
**If you update any file inside `compiler/builtins` you will need to do this for it to update inside Porffor otherwise your changes will have no effect.** Run `./porf precompile` to precompile. It may error during this, if so, you might have an error in your code or there could be a compiler error with Porffor (feel free to ask for help as soon as you encounter any errors with it).
|
30
30
|
|
31
31
|
<br>
|
32
32
|
|
File without changes
|
File without changes
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import { Valtype } from '../wasmSpec.js';
|
2
|
+
import { number } from './embedding.js';
|
3
|
+
import { log } from './log.js';
|
4
|
+
import Prefs from './prefs.js';
|
5
|
+
|
6
|
+
let pages = new Set();
|
7
|
+
export const setup = () => {
|
8
|
+
pages = new Set();
|
9
|
+
};
|
10
|
+
|
11
|
+
const getAllocType = itemType => {
|
12
|
+
switch (itemType) {
|
13
|
+
case 'i8': return 'bytestring';
|
14
|
+
case 'i16': return 'string';
|
15
|
+
|
16
|
+
default: return 'array';
|
17
|
+
}
|
18
|
+
};
|
19
|
+
|
20
|
+
export const alloc = ({ scope }, name, itemType) => {
|
21
|
+
const reason = Prefs.scopedPageNames ? `${getAllocType(itemType)}: ${scope.name}/${name}` : `${getAllocType(itemType)}: ${name}`;
|
22
|
+
|
23
|
+
if (pages.has(reason)) return number(pages.get(reason).ind, Valtype.i32);
|
24
|
+
|
25
|
+
if (reason.startsWith('array:')) pages.hasArray = true;
|
26
|
+
if (reason.startsWith('string:')) pages.hasString = true;
|
27
|
+
if (reason.startsWith('bytestring:')) pages.hasByteString = true;
|
28
|
+
if (reason.includes('string:')) pages.hasAnyString = true;
|
29
|
+
|
30
|
+
const ind = pages.size;
|
31
|
+
pages.set(reason, { ind, type });
|
32
|
+
|
33
|
+
scope.pages ??= new Map();
|
34
|
+
scope.pages.set(reason, { ind, type });
|
35
|
+
|
36
|
+
if (Prefs.allocLog) log('alloc', `allocated new page of memory (${ind}) | ${reason} (type: ${type})`);
|
37
|
+
|
38
|
+
return number(ind, Valtype.i32);
|
39
|
+
};
|
40
|
+
|
41
|
+
export const getStaticPages = () => pages;
|
package/compiler/assemble.js
CHANGED
@@ -21,7 +21,7 @@ const chHint = (topTier, baselineTier, strategy) => {
|
|
21
21
|
return (strategy | (baselineTier << 2) | (topTier << 4));
|
22
22
|
};
|
23
23
|
|
24
|
-
export default (funcs, globals, tags, pages, data, flags) => {
|
24
|
+
export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) => {
|
25
25
|
const types = [], typeCache = {};
|
26
26
|
|
27
27
|
const optLevel = parseInt(process.argv.find(x => x.startsWith('-O'))?.[2] ?? 1);
|
@@ -44,7 +44,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
44
44
|
|
45
45
|
let importFuncs = [];
|
46
46
|
|
47
|
-
if (optLevel < 1 || !Prefs.treeshakeWasmImports) {
|
47
|
+
if (optLevel < 1 || !Prefs.treeshakeWasmImports || noTreeshake) {
|
48
48
|
importFuncs = importedFuncs;
|
49
49
|
} else {
|
50
50
|
let imports = new Map();
|
@@ -94,7 +94,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
94
94
|
|
95
95
|
const importSection = importFuncs.length === 0 ? [] : createSection(
|
96
96
|
Section.import,
|
97
|
-
encodeVector(importFuncs.map(x => [ 0, ...encodeString(x.import), ExportDesc.func, getType(
|
97
|
+
encodeVector(importFuncs.map(x => [ 0, ...encodeString(x.import), ExportDesc.func, getType(typeof x.params === 'object' ? x.params : new Array(x.params).fill(valtypeBinary), new Array(x.returns).fill(valtypeBinary)) ]))
|
98
98
|
);
|
99
99
|
|
100
100
|
const funcSection = createSection(
|
@@ -116,7 +116,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
116
116
|
] ])
|
117
117
|
);
|
118
118
|
|
119
|
-
if (pages.has('func argc lut')) {
|
119
|
+
if (pages.has('func argc lut') && !data.addedFuncArgcLut) {
|
120
120
|
// generate func argc lut data
|
121
121
|
const bytes = [];
|
122
122
|
for (let i = 0; i < funcs.length; i++) {
|
@@ -128,6 +128,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
128
128
|
offset: pages.get('func argc lut').ind * pageSize,
|
129
129
|
bytes
|
130
130
|
});
|
131
|
+
data.addedFuncArgcLut = true;
|
131
132
|
}
|
132
133
|
|
133
134
|
// const t0 = performance.now();
|
package/compiler/builtins.js
CHANGED
@@ -32,13 +32,13 @@ export const importedFuncs = [
|
|
32
32
|
{
|
33
33
|
name: 'profile1',
|
34
34
|
import: 'y',
|
35
|
-
params:
|
35
|
+
params: [ Valtype.i32 ],
|
36
36
|
returns: 0
|
37
37
|
},
|
38
38
|
{
|
39
39
|
name: 'profile2',
|
40
40
|
import: 'z',
|
41
|
-
params:
|
41
|
+
params: [ Valtype.i32 ],
|
42
42
|
returns: 0
|
43
43
|
},
|
44
44
|
{
|
package/compiler/codegen.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { Blocktype, Opcodes, Valtype,
|
1
|
+
import { Blocktype, Opcodes, Valtype, ValtypeSize } from './wasmSpec.js';
|
2
2
|
import { ieee754_binary64, signedLEB128, unsignedLEB128, encodeVector } from './encoding.js';
|
3
3
|
import { operatorOpcode } from './expression.js';
|
4
4
|
import { BuiltinFuncs, BuiltinVars, importedFuncs, NULL, UNDEFINED } from './builtins.js';
|
@@ -181,12 +181,6 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
181
181
|
continue;
|
182
182
|
}
|
183
183
|
|
184
|
-
if (asm[0] === 'memory') {
|
185
|
-
allocPage(scope, 'asm instrinsic');
|
186
|
-
// todo: add to store/load offset insts
|
187
|
-
continue;
|
188
|
-
}
|
189
|
-
|
190
184
|
let inst = Opcodes[asm[0].replace('.', '_')];
|
191
185
|
if (inst == null) throw new Error(`inline asm: inst ${asm[0]} not found`);
|
192
186
|
|
@@ -433,57 +427,6 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
433
427
|
const rightLength = localTmp(scope, 'concat_right_length', Valtype.i32);
|
434
428
|
const leftLength = localTmp(scope, 'concat_left_length', Valtype.i32);
|
435
429
|
|
436
|
-
if (assign && Prefs.aotPointerOpt) {
|
437
|
-
const pointer = scope.arrays?.get(name ?? '$undeclared');
|
438
|
-
|
439
|
-
return [
|
440
|
-
// setup right
|
441
|
-
...right,
|
442
|
-
Opcodes.i32_to_u,
|
443
|
-
[ Opcodes.local_set, rightPointer ],
|
444
|
-
|
445
|
-
// calculate length
|
446
|
-
...number(0, Valtype.i32), // base 0 for store later
|
447
|
-
|
448
|
-
...number(pointer, Valtype.i32),
|
449
|
-
[ Opcodes.i32_load, 0, ...unsignedLEB128(0) ],
|
450
|
-
[ Opcodes.local_tee, leftLength ],
|
451
|
-
|
452
|
-
[ Opcodes.local_get, rightPointer ],
|
453
|
-
[ Opcodes.i32_load, 0, ...unsignedLEB128(0) ],
|
454
|
-
[ Opcodes.local_tee, rightLength ],
|
455
|
-
|
456
|
-
[ Opcodes.i32_add ],
|
457
|
-
|
458
|
-
// store length
|
459
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(pointer) ],
|
460
|
-
|
461
|
-
// copy right
|
462
|
-
// dst = out pointer + length size + current length * sizeof valtype
|
463
|
-
...number(pointer + ValtypeSize.i32, Valtype.i32),
|
464
|
-
|
465
|
-
[ Opcodes.local_get, leftLength ],
|
466
|
-
...number(bytestrings ? ValtypeSize.i8 : ValtypeSize.i16, Valtype.i32),
|
467
|
-
[ Opcodes.i32_mul ],
|
468
|
-
[ Opcodes.i32_add ],
|
469
|
-
|
470
|
-
// src = right pointer + length size
|
471
|
-
[ Opcodes.local_get, rightPointer ],
|
472
|
-
...number(ValtypeSize.i32, Valtype.i32),
|
473
|
-
[ Opcodes.i32_add ],
|
474
|
-
|
475
|
-
// size = right length * sizeof valtype
|
476
|
-
[ Opcodes.local_get, rightLength ],
|
477
|
-
...number(bytestrings ? ValtypeSize.i8 : ValtypeSize.i16, Valtype.i32),
|
478
|
-
[ Opcodes.i32_mul ],
|
479
|
-
|
480
|
-
[ ...Opcodes.memory_copy, 0x00, 0x00 ],
|
481
|
-
|
482
|
-
// return new string (page)
|
483
|
-
...number(pointer)
|
484
|
-
];
|
485
|
-
}
|
486
|
-
|
487
430
|
const leftPointer = localTmp(scope, 'concat_left_pointer', Valtype.i32);
|
488
431
|
|
489
432
|
// alloc/assign array
|
@@ -1807,7 +1750,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1807
1750
|
f64_store: { imms: 2, args: [ true, false ], returns: 0 },
|
1808
1751
|
|
1809
1752
|
// value
|
1810
|
-
i32_const: { imms: 1, args: [], returns:
|
1753
|
+
i32_const: { imms: 1, args: [], returns: 0 },
|
1811
1754
|
};
|
1812
1755
|
|
1813
1756
|
const opName = name.slice('__Porffor_wasm_'.length);
|
@@ -1999,8 +1942,8 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1999
1942
|
}
|
2000
1943
|
|
2001
1944
|
if (valtypeBinary !== Valtype.i32 && (
|
2002
|
-
(builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32)
|
2003
|
-
(importedFuncs[name] && name.startsWith('profile'))
|
1945
|
+
(builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32)
|
1946
|
+
// (importedFuncs[name] && name.startsWith('profile'))
|
2004
1947
|
)) {
|
2005
1948
|
out.push(Opcodes.i32_to);
|
2006
1949
|
}
|
@@ -2115,7 +2058,6 @@ const brTable = (input, bc, returns) => {
|
|
2115
2058
|
}
|
2116
2059
|
|
2117
2060
|
for (let i = 0; i < count; i++) {
|
2118
|
-
// if (i === 0) out.push([ Opcodes.block, returns, 'br table start' ]);
|
2119
2061
|
if (i === 0) out.push([ Opcodes.block, returns ]);
|
2120
2062
|
else out.push([ Opcodes.block, Blocktype.void ]);
|
2121
2063
|
}
|
@@ -2149,10 +2091,8 @@ const brTable = (input, bc, returns) => {
|
|
2149
2091
|
[ Opcodes.br_table, ...encodeVector(table), 0 ]
|
2150
2092
|
);
|
2151
2093
|
|
2152
|
-
//
|
2153
|
-
// (
|
2154
|
-
// dm me and if you are correct and the first person
|
2155
|
-
// I will somehow shout you out or something
|
2094
|
+
// sort the wrong way and then reverse
|
2095
|
+
// so strings ('default') are at the start before any numbers
|
2156
2096
|
const orderedBc = keys.sort((a, b) => b - a).reverse();
|
2157
2097
|
|
2158
2098
|
br = count - 1;
|
@@ -2178,10 +2118,10 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
|
|
2178
2118
|
return bc[known] ?? bc.default;
|
2179
2119
|
}
|
2180
2120
|
|
2181
|
-
if (Prefs.
|
2121
|
+
if (Prefs.typeswitchBrtable)
|
2182
2122
|
return brTable(type, bc, returns);
|
2183
2123
|
|
2184
|
-
const tmp = localTmp(scope, '#typeswitch_tmp', Valtype.i32);
|
2124
|
+
const tmp = localTmp(scope, '#typeswitch_tmp' + (Prefs.typeswitchUniqueTmp ? randId() : ''), Valtype.i32);
|
2185
2125
|
const out = [
|
2186
2126
|
...type,
|
2187
2127
|
[ Opcodes.local_set, tmp ],
|
@@ -2399,19 +2339,12 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2399
2339
|
|
2400
2340
|
// hack: .length setter
|
2401
2341
|
if (decl.left.type === 'MemberExpression' && decl.left.property.name === 'length') {
|
2402
|
-
const name = decl.left.object.name;
|
2403
|
-
const pointer = scope.arrays?.get(name);
|
2404
|
-
|
2405
|
-
const aotPointer = Prefs.aotPointerOpt && pointer != null;
|
2406
|
-
|
2407
2342
|
const newValueTmp = localTmp(scope, '__length_setter_tmp');
|
2408
2343
|
const pointerTmp = op === '=' ? null : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2409
2344
|
|
2410
2345
|
return [
|
2411
|
-
...(
|
2412
|
-
|
2413
|
-
Opcodes.i32_to_u
|
2414
|
-
]),
|
2346
|
+
...generate(scope, decl.left.object),
|
2347
|
+
Opcodes.i32_to_u,
|
2415
2348
|
...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2416
2349
|
|
2417
2350
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
@@ -2422,7 +2355,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2422
2355
|
[ Opcodes.local_tee, newValueTmp ],
|
2423
2356
|
|
2424
2357
|
Opcodes.i32_to_u,
|
2425
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1,
|
2358
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
2426
2359
|
|
2427
2360
|
[ Opcodes.local_get, newValueTmp ]
|
2428
2361
|
];
|
@@ -2430,21 +2363,14 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2430
2363
|
|
2431
2364
|
// arr[i]
|
2432
2365
|
if (decl.left.type === 'MemberExpression' && decl.left.computed) {
|
2433
|
-
const name = decl.left.object.name;
|
2434
|
-
const pointer = scope.arrays?.get(name);
|
2435
|
-
|
2436
|
-
const aotPointer = Prefs.aotPointerOpt && pointer != null;
|
2437
|
-
|
2438
2366
|
const newValueTmp = localTmp(scope, '__member_setter_val_tmp');
|
2439
2367
|
const pointerTmp = op === '=' ? -1 : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2440
2368
|
|
2441
2369
|
return [
|
2442
2370
|
...typeSwitch(scope, getNodeType(scope, decl.left.object), {
|
2443
2371
|
[TYPES.array]: [
|
2444
|
-
...(
|
2445
|
-
|
2446
|
-
Opcodes.i32_to_u
|
2447
|
-
]),
|
2372
|
+
...generate(scope, decl.left.object),
|
2373
|
+
Opcodes.i32_to_u,
|
2448
2374
|
|
2449
2375
|
// get index as valtype
|
2450
2376
|
...generate(scope, decl.left.property),
|
@@ -2453,39 +2379,22 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2453
2379
|
// turn into byte offset by * valtypeSize (4 for i32, 8 for i64/f64)
|
2454
2380
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
2455
2381
|
[ Opcodes.i32_mul ],
|
2456
|
-
|
2382
|
+
[ Opcodes.i32_add ],
|
2457
2383
|
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2458
2384
|
|
2459
2385
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2460
2386
|
[ Opcodes.local_get, pointerTmp ],
|
2461
|
-
[ Opcodes.load, 0,
|
2387
|
+
[ Opcodes.load, 0, ValtypeSize.i32 ]
|
2462
2388
|
], generate(scope, decl.right), [
|
2463
2389
|
[ Opcodes.local_get, pointerTmp ],
|
2464
|
-
[ Opcodes.i32_load8_u, 0,
|
2390
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2465
2391
|
], getNodeType(scope, decl.right), false, name, true)),
|
2466
2392
|
[ Opcodes.local_tee, newValueTmp ],
|
2467
2393
|
|
2468
|
-
[ Opcodes.store, 0,
|
2394
|
+
[ Opcodes.store, 0, ValtypeSize.i32 ]
|
2469
2395
|
],
|
2470
2396
|
|
2471
2397
|
default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
|
2472
|
-
|
2473
|
-
// [TYPES.string]: [
|
2474
|
-
// // turn into byte offset by * sizeof i16
|
2475
|
-
// ...number(ValtypeSize.i16, Valtype.i32),
|
2476
|
-
// [ Opcodes.i32_mul ],
|
2477
|
-
// ...(aotPointer ? [] : [ [ Opcodes.i32_add ] ]),
|
2478
|
-
// ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2479
|
-
|
2480
|
-
// ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2481
|
-
// [ Opcodes.local_get, pointerTmp ],
|
2482
|
-
// [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
2483
|
-
// ], generate(scope, decl.right), number(TYPES.string, Valtype.i32), getNodeType(scope, decl.right))),
|
2484
|
-
// [ Opcodes.local_tee, newValueTmp ],
|
2485
|
-
|
2486
|
-
// Opcodes.i32_to_u,
|
2487
|
-
// [ StoreOps.i16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
2488
|
-
// ]
|
2489
2398
|
}, Blocktype.void),
|
2490
2399
|
|
2491
2400
|
[ Opcodes.local_get, newValueTmp ]
|
@@ -2563,7 +2472,7 @@ const generateUnary = (scope, decl) => {
|
|
2563
2472
|
// * -1
|
2564
2473
|
|
2565
2474
|
if (decl.prefix && decl.argument.type === 'Literal' && typeof decl.argument.value === 'number') {
|
2566
|
-
// if
|
2475
|
+
// if -n, just return that as a const
|
2567
2476
|
return number(-1 * decl.argument.value);
|
2568
2477
|
}
|
2569
2478
|
|
@@ -2575,14 +2484,14 @@ const generateUnary = (scope, decl) => {
|
|
2575
2484
|
case '!':
|
2576
2485
|
const arg = decl.argument;
|
2577
2486
|
if (arg.type === 'UnaryExpression' && arg.operator === '!') {
|
2578
|
-
// !!x -> is x truthy
|
2487
|
+
// opt: !!x -> is x truthy
|
2579
2488
|
return truthy(scope, generate(scope, arg.argument), getNodeType(scope, arg.argument), false, false);
|
2580
2489
|
}
|
2490
|
+
|
2581
2491
|
// !=
|
2582
|
-
return falsy(scope, generate(scope,
|
2492
|
+
return falsy(scope, generate(scope, arg), getNodeType(scope, arg), false, false);
|
2583
2493
|
|
2584
2494
|
case '~':
|
2585
|
-
// todo: does not handle Infinity properly (should convert to 0) (but opt const converting saves us sometimes)
|
2586
2495
|
return [
|
2587
2496
|
...generate(scope, decl.argument),
|
2588
2497
|
Opcodes.i32_to,
|
@@ -3207,16 +3116,6 @@ const allocPage = (scope, reason, type) => {
|
|
3207
3116
|
return ind;
|
3208
3117
|
};
|
3209
3118
|
|
3210
|
-
// todo: add scope.pages
|
3211
|
-
const freePage = reason => {
|
3212
|
-
const { ind } = pages.get(reason);
|
3213
|
-
pages.delete(reason);
|
3214
|
-
|
3215
|
-
if (Prefs.allocLog) log('alloc', `freed page of memory (${ind}) | ${reason}`);
|
3216
|
-
|
3217
|
-
return ind;
|
3218
|
-
};
|
3219
|
-
|
3220
3119
|
const itemTypeToValtype = {
|
3221
3120
|
i32: 'i32',
|
3222
3121
|
i64: 'i64',
|
@@ -3270,7 +3169,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3270
3169
|
firstAssign = true;
|
3271
3170
|
|
3272
3171
|
// todo: can we just have 1 undeclared array? probably not? but this is not really memory efficient
|
3273
|
-
const uniqueName = name === '$undeclared' ? name +
|
3172
|
+
const uniqueName = name === '$undeclared' ? name + randId() : name;
|
3274
3173
|
|
3275
3174
|
let page;
|
3276
3175
|
if (Prefs.scopedPageNames) page = allocPage(scope, `${getAllocType(itemType)}: ${scope.name}/${uniqueName}`, itemType);
|
@@ -3291,7 +3190,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3291
3190
|
const valtype = itemTypeToValtype[itemType];
|
3292
3191
|
const length = elements.length;
|
3293
3192
|
|
3294
|
-
if (
|
3193
|
+
if (Prefs.data && firstAssign && useRawElements) {
|
3295
3194
|
// if length is 0 memory/data will just be 0000... anyway
|
3296
3195
|
if (length !== 0) {
|
3297
3196
|
let bytes = compileBytes(length, 'i32');
|
@@ -3359,7 +3258,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3359
3258
|
return [ out, pointer ];
|
3360
3259
|
};
|
3361
3260
|
|
3362
|
-
const storeArray = (scope, array, index, element
|
3261
|
+
const storeArray = (scope, array, index, element) => {
|
3363
3262
|
if (!Array.isArray(element)) element = generate(scope, element);
|
3364
3263
|
if (typeof index === 'number') index = number(index);
|
3365
3264
|
|
@@ -3371,26 +3270,25 @@ const storeArray = (scope, array, index, element, aotPointer = null) => {
|
|
3371
3270
|
Opcodes.i32_to_u,
|
3372
3271
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
3373
3272
|
[ Opcodes.i32_mul ],
|
3374
|
-
|
3375
|
-
|
3376
|
-
|
3377
|
-
|
3378
|
-
]),
|
3273
|
+
|
3274
|
+
...array,
|
3275
|
+
Opcodes.i32_to_u,
|
3276
|
+
[ Opcodes.i32_add ],
|
3379
3277
|
[ Opcodes.local_set, offset ],
|
3380
3278
|
|
3381
3279
|
// store value
|
3382
3280
|
[ Opcodes.local_get, offset ],
|
3383
3281
|
...generate(scope, element),
|
3384
|
-
[ Opcodes.store, 0,
|
3282
|
+
[ Opcodes.store, 0, ValtypeSize.i32 ],
|
3385
3283
|
|
3386
3284
|
// store type
|
3387
3285
|
[ Opcodes.local_get, offset ],
|
3388
3286
|
...getNodeType(scope, element),
|
3389
|
-
[ Opcodes.i32_store8, 0,
|
3287
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
3390
3288
|
];
|
3391
3289
|
};
|
3392
3290
|
|
3393
|
-
const loadArray = (scope, array, index
|
3291
|
+
const loadArray = (scope, array, index) => {
|
3394
3292
|
if (typeof index === 'number') index = number(index);
|
3395
3293
|
|
3396
3294
|
const offset = localTmp(scope, '#loadArray_offset', Valtype.i32);
|
@@ -3401,20 +3299,19 @@ const loadArray = (scope, array, index, aotPointer = null) => {
|
|
3401
3299
|
Opcodes.i32_to_u,
|
3402
3300
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
3403
3301
|
[ Opcodes.i32_mul ],
|
3404
|
-
|
3405
|
-
|
3406
|
-
|
3407
|
-
|
3408
|
-
]),
|
3302
|
+
|
3303
|
+
...array,
|
3304
|
+
Opcodes.i32_to_u,
|
3305
|
+
[ Opcodes.i32_add ],
|
3409
3306
|
[ Opcodes.local_set, offset ],
|
3410
3307
|
|
3411
3308
|
// load value
|
3412
3309
|
[ Opcodes.local_get, offset ],
|
3413
|
-
[ Opcodes.load, 0,
|
3310
|
+
[ Opcodes.load, 0, ValtypeSize.i32 ],
|
3414
3311
|
|
3415
3312
|
// load type
|
3416
3313
|
[ Opcodes.local_get, offset ],
|
3417
|
-
[ Opcodes.i32_load8_u, 0,
|
3314
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
3418
3315
|
];
|
3419
3316
|
};
|
3420
3317
|
|
@@ -3465,9 +3362,6 @@ const withType = (scope, wasm, type) => [
|
|
3465
3362
|
|
3466
3363
|
const generateMember = (scope, decl, _global, _name) => {
|
3467
3364
|
const name = decl.object.name;
|
3468
|
-
const pointer = scope.arrays?.get(name);
|
3469
|
-
|
3470
|
-
const aotPointer = Prefs.aotPointerOpt && pointer;
|
3471
3365
|
|
3472
3366
|
// hack: .name
|
3473
3367
|
if (decl.property.name === 'name') {
|
@@ -3502,18 +3396,16 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3502
3396
|
}
|
3503
3397
|
|
3504
3398
|
if (builtinFuncs[name]) return withType(scope, number(builtinFuncs[name].typedParams ? (builtinFuncs[name].params.length / 2) : builtinFuncs[name].params.length), TYPES.number);
|
3505
|
-
if (importedFuncs[name]) return withType(scope, number(importedFuncs[name].params), TYPES.number);
|
3399
|
+
if (importedFuncs[name]) return withType(scope, number(importedFuncs[name].params.length ?? importedFuncs[name].params), TYPES.number);
|
3506
3400
|
if (internalConstrs[name]) return withType(scope, number(internalConstrs[name].length ?? 0), TYPES.number);
|
3507
3401
|
|
3508
3402
|
if (Prefs.fastLength) {
|
3509
3403
|
// presume valid length object
|
3510
3404
|
return [
|
3511
|
-
...(
|
3512
|
-
|
3513
|
-
Opcodes.i32_to_u
|
3514
|
-
]),
|
3405
|
+
...generate(scope, decl.object),
|
3406
|
+
Opcodes.i32_to_u,
|
3515
3407
|
|
3516
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1,
|
3408
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3517
3409
|
Opcodes.i32_from_u
|
3518
3410
|
];
|
3519
3411
|
}
|
@@ -3522,12 +3414,10 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3522
3414
|
const known = knownType(scope, type);
|
3523
3415
|
if (known != null) {
|
3524
3416
|
if ([ TYPES.string, TYPES.bytestring, TYPES.array ].includes(known)) return [
|
3525
|
-
...(
|
3526
|
-
|
3527
|
-
Opcodes.i32_to_u
|
3528
|
-
]),
|
3417
|
+
...generate(scope, decl.object),
|
3418
|
+
Opcodes.i32_to_u,
|
3529
3419
|
|
3530
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1,
|
3420
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3531
3421
|
Opcodes.i32_from_u
|
3532
3422
|
];
|
3533
3423
|
|
@@ -3537,12 +3427,10 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3537
3427
|
return [
|
3538
3428
|
...typeIsOneOf(getNodeType(scope, decl.object), [ TYPES.string, TYPES.bytestring, TYPES.array ]),
|
3539
3429
|
[ Opcodes.if, valtypeBinary ],
|
3540
|
-
...(
|
3541
|
-
|
3542
|
-
Opcodes.i32_to_u
|
3543
|
-
]),
|
3430
|
+
...generate(scope, decl.object),
|
3431
|
+
Opcodes.i32_to_u,
|
3544
3432
|
|
3545
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1,
|
3433
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3546
3434
|
Opcodes.i32_from_u,
|
3547
3435
|
|
3548
3436
|
...setLastType(scope, TYPES.number),
|
@@ -3594,7 +3482,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3594
3482
|
|
3595
3483
|
return typeSwitch(scope, getNodeType(scope, decl.object), {
|
3596
3484
|
[TYPES.array]: [
|
3597
|
-
...loadArray(scope, object, property
|
3485
|
+
...loadArray(scope, object, property),
|
3598
3486
|
...setLastType(scope)
|
3599
3487
|
],
|
3600
3488
|
|
@@ -3611,14 +3499,12 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3611
3499
|
...number(ValtypeSize.i16, Valtype.i32),
|
3612
3500
|
[ Opcodes.i32_mul ],
|
3613
3501
|
|
3614
|
-
...
|
3615
|
-
|
3616
|
-
|
3617
|
-
[ Opcodes.i32_add ]
|
3618
|
-
]),
|
3502
|
+
...object,
|
3503
|
+
Opcodes.i32_to_u,
|
3504
|
+
[ Opcodes.i32_add ],
|
3619
3505
|
|
3620
3506
|
// load current string ind {arg}
|
3621
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1,
|
3507
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
3622
3508
|
|
3623
3509
|
// store to new string ind 0
|
3624
3510
|
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
|
@@ -3637,14 +3523,12 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3637
3523
|
...property,
|
3638
3524
|
Opcodes.i32_to_u,
|
3639
3525
|
|
3640
|
-
...
|
3641
|
-
|
3642
|
-
|
3643
|
-
[ Opcodes.i32_add ]
|
3644
|
-
]),
|
3526
|
+
...object,
|
3527
|
+
Opcodes.i32_to_u,
|
3528
|
+
[ Opcodes.i32_add ],
|
3645
3529
|
|
3646
3530
|
// load current string ind {arg}
|
3647
|
-
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(
|
3531
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
3648
3532
|
|
3649
3533
|
// store to new string ind 0
|
3650
3534
|
[ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
|
@@ -3658,7 +3542,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3658
3542
|
});
|
3659
3543
|
};
|
3660
3544
|
|
3661
|
-
const randId = () => Math.random().toString(16).slice(
|
3545
|
+
const randId = () => Math.random().toString(16).slice(1, -2).padEnd(12, '0');
|
3662
3546
|
|
3663
3547
|
const objectHack = node => {
|
3664
3548
|
if (!node) return node;
|
@@ -3710,7 +3594,7 @@ const generateFunc = (scope, decl) => {
|
|
3710
3594
|
if (decl.async) return todo(scope, 'async functions are not supported');
|
3711
3595
|
if (decl.generator) return todo(scope, 'generator functions are not supported');
|
3712
3596
|
|
3713
|
-
const name = decl.id ? decl.id.name : `
|
3597
|
+
const name = decl.id ? decl.id.name : `anonymous${randId()}`;
|
3714
3598
|
const params = decl.params ?? [];
|
3715
3599
|
|
3716
3600
|
// TODO: share scope/locals between !!!
|
@@ -3971,19 +3855,8 @@ export default program => {
|
|
3971
3855
|
data = [];
|
3972
3856
|
currentFuncIndex = importedFuncs.length;
|
3973
3857
|
|
3974
|
-
globalThis.valtype = 'f64';
|
3975
|
-
|
3976
|
-
const valtypeOpt = process.argv.find(x => x.startsWith('--valtype='));
|
3977
|
-
if (valtypeOpt) valtype = valtypeOpt.split('=')[1];
|
3978
|
-
|
3979
|
-
globalThis.valtypeBinary = Valtype[valtype];
|
3980
|
-
|
3981
3858
|
const valtypeInd = ['i32', 'i64', 'f64'].indexOf(valtype);
|
3982
3859
|
|
3983
|
-
globalThis.pageSize = PageSize;
|
3984
|
-
const pageSizeOpt = process.argv.find(x => x.startsWith('--page-size='));
|
3985
|
-
if (pageSizeOpt) pageSize = parseInt(pageSizeOpt.split('=')[1]) * 1024;
|
3986
|
-
|
3987
3860
|
// set generic opcodes for current valtype
|
3988
3861
|
Opcodes.const = [ Opcodes.i32_const, Opcodes.i64_const, Opcodes.f64_const ][valtypeInd];
|
3989
3862
|
Opcodes.eq = [ Opcodes.i32_eq, Opcodes.i64_eq, Opcodes.f64_eq ][valtypeInd];
|