porffor 0.16.0-688a50c13 → 0.16.0-79cd8c0c8
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/builtins/date.ts +4 -2
- package/compiler/builtins/set.ts +4 -2
- package/compiler/codegen.js +291 -195
- package/compiler/cyclone.js +11 -11
- package/compiler/generated_builtins.js +18 -18
- package/compiler/opt.js +5 -7
- package/compiler/parse.js +1 -1
- package/compiler/precompile.js +6 -11
- package/compiler/prefs.js +1 -1
- package/compiler/prototype.js +43 -34
- package/compiler/wrap.js +15 -15
- package/package.json +4 -2
- package/runner/index.js +3 -8
- package/a.txt +0 -457
- package/b.txt +0 -457
- package/compiler/allocators/grow.js +0 -26
- package/compiler/allocators/index.js +0 -10
- package/compiler/allocators/static.js +0 -42
package/compiler/codegen.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
import { Blocktype, Opcodes, Valtype, ValtypeSize } from './wasmSpec.js';
|
2
|
-
import { ieee754_binary64, signedLEB128, unsignedLEB128, encodeVector
|
1
|
+
import { Blocktype, Opcodes, Valtype, PageSize, ValtypeSize } from './wasmSpec.js';
|
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';
|
5
5
|
import { PrototypeFuncs } from './prototype.js';
|
@@ -9,16 +9,15 @@ import * as Rhemyn from '../rhemyn/compile.js';
|
|
9
9
|
import parse from './parse.js';
|
10
10
|
import { log } from './log.js';
|
11
11
|
import Prefs from './prefs.js';
|
12
|
-
import Allocator from './allocators/index.js';
|
13
12
|
|
14
13
|
let globals = {};
|
14
|
+
let globalInd = 0;
|
15
15
|
let tags = [];
|
16
16
|
let funcs = [];
|
17
17
|
let exceptions = [];
|
18
18
|
let funcIndex = {};
|
19
19
|
let currentFuncIndex = importedFuncs.length;
|
20
20
|
let builtinFuncs = {}, builtinVars = {}, prototypeFuncs = {};
|
21
|
-
let allocator;
|
22
21
|
|
23
22
|
class TodoError extends Error {
|
24
23
|
constructor(message) {
|
@@ -182,6 +181,12 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
182
181
|
continue;
|
183
182
|
}
|
184
183
|
|
184
|
+
if (asm[0] === 'memory') {
|
185
|
+
allocPage(scope, 'asm instrinsic');
|
186
|
+
// todo: add to store/load offset insts
|
187
|
+
continue;
|
188
|
+
}
|
189
|
+
|
185
190
|
let inst = Opcodes[asm[0].replace('.', '_')];
|
186
191
|
if (inst == null) throw new Error(`inline asm: inst ${asm[0]} not found`);
|
187
192
|
|
@@ -428,12 +433,63 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
428
433
|
const rightLength = localTmp(scope, 'concat_right_length', Valtype.i32);
|
429
434
|
const leftLength = localTmp(scope, 'concat_left_length', Valtype.i32);
|
430
435
|
|
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
|
+
|
431
487
|
const leftPointer = localTmp(scope, 'concat_left_pointer', Valtype.i32);
|
432
488
|
|
433
489
|
// alloc/assign array
|
434
490
|
const [ , pointer ] = makeArray(scope, {
|
435
491
|
rawElements: new Array(0)
|
436
|
-
}, global, name, true, 'i16'
|
492
|
+
}, global, name, true, 'i16');
|
437
493
|
|
438
494
|
return [
|
439
495
|
// setup left
|
@@ -447,7 +503,7 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
447
503
|
[ Opcodes.local_set, rightPointer ],
|
448
504
|
|
449
505
|
// calculate length
|
450
|
-
...
|
506
|
+
...number(0, Valtype.i32), // base 0 for store later
|
451
507
|
|
452
508
|
[ Opcodes.local_get, leftPointer ],
|
453
509
|
[ Opcodes.i32_load, 0, ...unsignedLEB128(0) ],
|
@@ -460,13 +516,11 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
460
516
|
[ Opcodes.i32_add ],
|
461
517
|
|
462
518
|
// store length
|
463
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1,
|
519
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(pointer) ],
|
464
520
|
|
465
521
|
// copy left
|
466
522
|
// dst = out pointer + length size
|
467
|
-
...pointer,
|
468
|
-
...number(ValtypeSize.i32, Valtype.i32),
|
469
|
-
[ Opcodes.i32_add ],
|
523
|
+
...number(pointer + ValtypeSize.i32, Valtype.i32),
|
470
524
|
|
471
525
|
// src = left pointer + length size
|
472
526
|
[ Opcodes.local_get, leftPointer ],
|
@@ -479,9 +533,7 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
479
533
|
|
480
534
|
// copy right
|
481
535
|
// dst = out pointer + length size + left length * sizeof valtype
|
482
|
-
...pointer,
|
483
|
-
...number(ValtypeSize.i32, Valtype.i32),
|
484
|
-
[ Opcodes.i32_add ],
|
536
|
+
...number(pointer + ValtypeSize.i32, Valtype.i32),
|
485
537
|
|
486
538
|
[ Opcodes.local_get, leftLength ],
|
487
539
|
...number(bytestrings ? ValtypeSize.i8 : ValtypeSize.i16, Valtype.i32),
|
@@ -501,8 +553,7 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
501
553
|
[ ...Opcodes.memory_copy, 0x00, 0x00 ],
|
502
554
|
|
503
555
|
// return new string (page)
|
504
|
-
...pointer
|
505
|
-
Opcodes.i32_from_u
|
556
|
+
...number(pointer)
|
506
557
|
];
|
507
558
|
};
|
508
559
|
|
@@ -618,10 +669,10 @@ const compareStrings = (scope, left, right, bytestrings = false) => {
|
|
618
669
|
};
|
619
670
|
|
620
671
|
const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMode = undefined) => {
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
672
|
+
if (isIntToFloatOp(wasm[wasm.length - 1])) return [
|
673
|
+
...wasm,
|
674
|
+
...(!intIn && intOut ? [ Opcodes.i32_to_u ] : [])
|
675
|
+
];
|
625
676
|
// if (isIntOp(wasm[wasm.length - 1])) return [ ...wasm ];
|
626
677
|
|
627
678
|
// todo/perf: use knownType and custom bytecode here instead of typeSwitch
|
@@ -1040,9 +1091,9 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
|
|
1040
1091
|
|
1041
1092
|
let baseGlobalIdx, i = 0;
|
1042
1093
|
for (const type of globalTypes) {
|
1043
|
-
if (baseGlobalIdx === undefined) baseGlobalIdx =
|
1094
|
+
if (baseGlobalIdx === undefined) baseGlobalIdx = globalInd;
|
1044
1095
|
|
1045
|
-
globals[globalNames[i] ?? `${name}_global_${i}`] = { idx:
|
1096
|
+
globals[globalNames[i] ?? `${name}_global_${i}`] = { idx: globalInd++, type, init: globalInits[i] ?? 0 };
|
1046
1097
|
i++;
|
1047
1098
|
}
|
1048
1099
|
|
@@ -1055,15 +1106,11 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
|
|
1055
1106
|
}
|
1056
1107
|
}
|
1057
1108
|
|
1058
|
-
if (table) {
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
inst.push(...unsignedLEB128(allocPage({}, 'func argc lut') * pageSize));
|
1063
|
-
}
|
1109
|
+
if (table) for (const inst of wasm) {
|
1110
|
+
if (inst[0] === Opcodes.i32_load16_u && inst.at(-1) === 'read_argc') {
|
1111
|
+
inst.splice(2, 99);
|
1112
|
+
inst.push(...unsignedLEB128(allocPage({}, 'func argc lut') * pageSize));
|
1064
1113
|
}
|
1065
|
-
|
1066
|
-
funcs.table = true;
|
1067
1114
|
}
|
1068
1115
|
|
1069
1116
|
func.wasm = wasm;
|
@@ -1678,7 +1725,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1678
1725
|
}, generate(scope, decl.arguments[0] ?? DEFAULT_VALUE), getNodeType(scope, decl.arguments[0] ?? DEFAULT_VALUE), protoLocal, protoLocal2, (length, itemType) => {
|
1679
1726
|
return makeArray(scope, {
|
1680
1727
|
rawElements: new Array(length)
|
1681
|
-
}, _global, _name, true, itemType
|
1728
|
+
}, _global, _name, true, itemType);
|
1682
1729
|
}, () => {
|
1683
1730
|
optUnused = true;
|
1684
1731
|
return unusedValue;
|
@@ -2068,6 +2115,7 @@ const brTable = (input, bc, returns) => {
|
|
2068
2115
|
}
|
2069
2116
|
|
2070
2117
|
for (let i = 0; i < count; i++) {
|
2118
|
+
// if (i === 0) out.push([ Opcodes.block, returns, 'br table start' ]);
|
2071
2119
|
if (i === 0) out.push([ Opcodes.block, returns ]);
|
2072
2120
|
else out.push([ Opcodes.block, Blocktype.void ]);
|
2073
2121
|
}
|
@@ -2101,8 +2149,10 @@ const brTable = (input, bc, returns) => {
|
|
2101
2149
|
[ Opcodes.br_table, ...encodeVector(table), 0 ]
|
2102
2150
|
);
|
2103
2151
|
|
2104
|
-
// sort the wrong way and then reverse
|
2105
|
-
//
|
2152
|
+
// if you can guess why we sort the wrong way and then reverse
|
2153
|
+
// (instead of just sorting the correct way)
|
2154
|
+
// dm me and if you are correct and the first person
|
2155
|
+
// I will somehow shout you out or something
|
2106
2156
|
const orderedBc = keys.sort((a, b) => b - a).reverse();
|
2107
2157
|
|
2108
2158
|
br = count - 1;
|
@@ -2128,7 +2178,7 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
|
|
2128
2178
|
return bc[known] ?? bc.default;
|
2129
2179
|
}
|
2130
2180
|
|
2131
|
-
if (Prefs.
|
2181
|
+
if (Prefs.typeswitchUseBrtable)
|
2132
2182
|
return brTable(type, bc, returns);
|
2133
2183
|
|
2134
2184
|
const tmp = localTmp(scope, '#typeswitch_tmp' + (Prefs.typeswitchUniqueTmp ? randId() : ''), Valtype.i32);
|
@@ -2183,11 +2233,11 @@ const allocVar = (scope, name, global = false, type = true) => {
|
|
2183
2233
|
return target[name].idx;
|
2184
2234
|
}
|
2185
2235
|
|
2186
|
-
let idx = global ?
|
2236
|
+
let idx = global ? globalInd++ : scope.localInd++;
|
2187
2237
|
target[name] = { idx, type: valtypeBinary };
|
2188
2238
|
|
2189
2239
|
if (type) {
|
2190
|
-
let typeIdx = global ?
|
2240
|
+
let typeIdx = global ? globalInd++ : scope.localInd++;
|
2191
2241
|
target[name + '#type'] = { idx: typeIdx, type: Valtype.i32, name };
|
2192
2242
|
}
|
2193
2243
|
|
@@ -2280,10 +2330,24 @@ const generateVar = (scope, decl) => {
|
|
2280
2330
|
}
|
2281
2331
|
|
2282
2332
|
if (x.init) {
|
2283
|
-
|
2333
|
+
// if (isFuncType(x.init.type)) {
|
2334
|
+
// // let a = function () { ... }
|
2335
|
+
// x.init.id = { name };
|
2336
|
+
|
2337
|
+
// const func = generateFunc(scope, x.init);
|
2338
|
+
|
2339
|
+
// out.push(
|
2340
|
+
// ...number(func.index - importedFuncs.length),
|
2341
|
+
// [ global ? Opcodes.global_set : Opcodes.local_set, idx ],
|
2342
|
+
|
2343
|
+
// ...setType(scope, name, TYPES.function)
|
2344
|
+
// );
|
2345
|
+
|
2346
|
+
// continue;
|
2347
|
+
// }
|
2284
2348
|
|
2285
2349
|
const generated = generate(scope, x.init, global, name);
|
2286
|
-
if (
|
2350
|
+
if (scope.arrays?.get(name) != null) {
|
2287
2351
|
// hack to set local as pointer before
|
2288
2352
|
out.push(...number(scope.arrays.get(name)), [ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
|
2289
2353
|
if (generated.at(-1) == Opcodes.i32_from_u) generated.pop();
|
@@ -2335,12 +2399,19 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2335
2399
|
|
2336
2400
|
// hack: .length setter
|
2337
2401
|
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
|
+
|
2338
2407
|
const newValueTmp = localTmp(scope, '__length_setter_tmp');
|
2339
2408
|
const pointerTmp = op === '=' ? null : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2340
2409
|
|
2341
2410
|
return [
|
2342
|
-
...
|
2343
|
-
|
2411
|
+
...(aotPointer ? number(0, Valtype.i32) : [
|
2412
|
+
...generate(scope, decl.left.object),
|
2413
|
+
Opcodes.i32_to_u
|
2414
|
+
]),
|
2344
2415
|
...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2345
2416
|
|
2346
2417
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
@@ -2351,7 +2422,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2351
2422
|
[ Opcodes.local_tee, newValueTmp ],
|
2352
2423
|
|
2353
2424
|
Opcodes.i32_to_u,
|
2354
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
2425
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(aotPointer ? pointer : 0) ],
|
2355
2426
|
|
2356
2427
|
[ Opcodes.local_get, newValueTmp ]
|
2357
2428
|
];
|
@@ -2359,14 +2430,21 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2359
2430
|
|
2360
2431
|
// arr[i]
|
2361
2432
|
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
|
+
|
2362
2438
|
const newValueTmp = localTmp(scope, '__member_setter_val_tmp');
|
2363
2439
|
const pointerTmp = op === '=' ? -1 : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2364
2440
|
|
2365
2441
|
return [
|
2366
2442
|
...typeSwitch(scope, getNodeType(scope, decl.left.object), {
|
2367
2443
|
[TYPES.array]: [
|
2368
|
-
...
|
2369
|
-
|
2444
|
+
...(aotPointer ? [] : [
|
2445
|
+
...generate(scope, decl.left.object),
|
2446
|
+
Opcodes.i32_to_u
|
2447
|
+
]),
|
2370
2448
|
|
2371
2449
|
// get index as valtype
|
2372
2450
|
...generate(scope, decl.left.property),
|
@@ -2375,22 +2453,39 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2375
2453
|
// turn into byte offset by * valtypeSize (4 for i32, 8 for i64/f64)
|
2376
2454
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
2377
2455
|
[ Opcodes.i32_mul ],
|
2378
|
-
[ Opcodes.i32_add ],
|
2456
|
+
...(aotPointer ? [] : [ [ Opcodes.i32_add ] ]),
|
2379
2457
|
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2380
2458
|
|
2381
2459
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2382
2460
|
[ Opcodes.local_get, pointerTmp ],
|
2383
|
-
[ Opcodes.load, 0, ValtypeSize.i32 ]
|
2461
|
+
[ Opcodes.load, 0, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
2384
2462
|
], generate(scope, decl.right), [
|
2385
2463
|
[ Opcodes.local_get, pointerTmp ],
|
2386
|
-
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2464
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32 + ValtypeSize[valtype]) ]
|
2387
2465
|
], getNodeType(scope, decl.right), false, name, true)),
|
2388
2466
|
[ Opcodes.local_tee, newValueTmp ],
|
2389
2467
|
|
2390
|
-
[ Opcodes.store, 0, ValtypeSize.i32 ]
|
2468
|
+
[ Opcodes.store, 0, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
2391
2469
|
],
|
2392
2470
|
|
2393
2471
|
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
|
+
// ]
|
2394
2489
|
}, Blocktype.void),
|
2395
2490
|
|
2396
2491
|
[ Opcodes.local_get, newValueTmp ]
|
@@ -2774,12 +2869,12 @@ const generateForOf = (scope, decl) => {
|
|
2774
2869
|
|
2775
2870
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
2776
2871
|
// hack: this is naughty and will break things!
|
2777
|
-
let newOut = number(0, Valtype.
|
2872
|
+
let newOut = number(0, Valtype.f64), newPointer = -1;
|
2778
2873
|
if (pages.hasAnyString) {
|
2779
2874
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
2780
2875
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
2781
|
-
rawElements: new Array(
|
2782
|
-
}, isGlobal, leftName, true, 'i16'
|
2876
|
+
rawElements: new Array(1)
|
2877
|
+
}, isGlobal, leftName, true, 'i16');
|
2783
2878
|
}
|
2784
2879
|
|
2785
2880
|
// set type for local
|
@@ -2826,28 +2921,23 @@ const generateForOf = (scope, decl) => {
|
|
2826
2921
|
[TYPES.string]: [
|
2827
2922
|
...setType(scope, leftName, TYPES.string),
|
2828
2923
|
|
2924
|
+
[ Opcodes.loop, Blocktype.void ],
|
2925
|
+
|
2829
2926
|
// setup new/out array
|
2830
2927
|
...newOut,
|
2928
|
+
[ Opcodes.drop ],
|
2831
2929
|
|
2832
|
-
//
|
2833
|
-
...number(1, Valtype.i32),
|
2834
|
-
[ Opcodes.i32_store, 0, 0 ],
|
2835
|
-
|
2836
|
-
[ Opcodes.loop, Blocktype.void ],
|
2837
|
-
|
2838
|
-
// use as pointer for store later
|
2839
|
-
...newPointer,
|
2930
|
+
...number(0, Valtype.i32), // base 0 for store after
|
2840
2931
|
|
2841
2932
|
// load current string ind {arg}
|
2842
2933
|
[ Opcodes.local_get, pointer ],
|
2843
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
2934
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(ValtypeSize.i32) ],
|
2844
2935
|
|
2845
2936
|
// store to new string ind 0
|
2846
|
-
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
2937
|
+
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
|
2847
2938
|
|
2848
2939
|
// return new string (page)
|
2849
|
-
...newPointer,
|
2850
|
-
Opcodes.i32_from_u,
|
2940
|
+
...number(newPointer),
|
2851
2941
|
|
2852
2942
|
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
2853
2943
|
|
@@ -2879,30 +2969,25 @@ const generateForOf = (scope, decl) => {
|
|
2879
2969
|
[TYPES.bytestring]: [
|
2880
2970
|
...setType(scope, leftName, TYPES.bytestring),
|
2881
2971
|
|
2972
|
+
[ Opcodes.loop, Blocktype.void ],
|
2973
|
+
|
2882
2974
|
// setup new/out array
|
2883
2975
|
...newOut,
|
2976
|
+
[ Opcodes.drop ],
|
2884
2977
|
|
2885
|
-
//
|
2886
|
-
...number(1, Valtype.i32),
|
2887
|
-
[ Opcodes.i32_store, 0, 0 ],
|
2888
|
-
|
2889
|
-
[ Opcodes.loop, Blocktype.void ],
|
2890
|
-
|
2891
|
-
// use as pointer for store later
|
2892
|
-
...newPointer,
|
2978
|
+
...number(0, Valtype.i32), // base 0 for store after
|
2893
2979
|
|
2894
2980
|
// load current string ind {arg}
|
2895
2981
|
[ Opcodes.local_get, pointer ],
|
2896
2982
|
[ Opcodes.local_get, counter ],
|
2897
2983
|
[ Opcodes.i32_add ],
|
2898
|
-
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
|
2984
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
2899
2985
|
|
2900
2986
|
// store to new string ind 0
|
2901
|
-
[ Opcodes.i32_store8, 0, ValtypeSize.i32 ],
|
2987
|
+
[ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
|
2902
2988
|
|
2903
2989
|
// return new string (page)
|
2904
|
-
...newPointer,
|
2905
|
-
Opcodes.i32_from_u,
|
2990
|
+
...number(newPointer),
|
2906
2991
|
|
2907
2992
|
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
2908
2993
|
|
@@ -3122,6 +3207,16 @@ const allocPage = (scope, reason, type) => {
|
|
3122
3207
|
return ind;
|
3123
3208
|
};
|
3124
3209
|
|
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
|
+
|
3125
3220
|
const itemTypeToValtype = {
|
3126
3221
|
i32: 'i32',
|
3127
3222
|
i64: 'i64',
|
@@ -3156,84 +3251,86 @@ const compileBytes = (val, itemType) => {
|
|
3156
3251
|
}
|
3157
3252
|
};
|
3158
3253
|
|
3159
|
-
const
|
3160
|
-
|
3161
|
-
|
3162
|
-
|
3163
|
-
|
3164
|
-
|
3165
|
-
else pages.hasString = true;
|
3254
|
+
const getAllocType = itemType => {
|
3255
|
+
switch (itemType) {
|
3256
|
+
case 'i8': return 'bytestring';
|
3257
|
+
case 'i16': return 'string';
|
3258
|
+
|
3259
|
+
default: return 'array';
|
3166
3260
|
}
|
3261
|
+
};
|
3167
3262
|
|
3263
|
+
const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty = false, itemType = valtype, typed = false) => {
|
3168
3264
|
const out = [];
|
3169
3265
|
|
3170
|
-
|
3266
|
+
scope.arrays ??= new Map();
|
3171
3267
|
|
3172
|
-
|
3173
|
-
|
3268
|
+
let firstAssign = false;
|
3269
|
+
if (!scope.arrays.has(name) || name === '$undeclared') {
|
3270
|
+
firstAssign = true;
|
3174
3271
|
|
3175
|
-
|
3176
|
-
|
3272
|
+
// todo: can we just have 1 undeclared array? probably not? but this is not really memory efficient
|
3273
|
+
const uniqueName = name === '$undeclared' ? name + randId() : name;
|
3177
3274
|
|
3178
|
-
|
3275
|
+
let page;
|
3276
|
+
if (Prefs.scopedPageNames) page = allocPage(scope, `${getAllocType(itemType)}: ${scope.name}/${uniqueName}`, itemType);
|
3277
|
+
else page = allocPage(scope, `${getAllocType(itemType)}: ${uniqueName}`, itemType);
|
3179
3278
|
|
3180
|
-
|
3181
|
-
|
3182
|
-
|
3183
|
-
|
3184
|
-
...allocated,
|
3185
|
-
[ Opcodes.local_set, tmp ]
|
3186
|
-
);
|
3279
|
+
// hack: use 1 for page 0 pointer for fast truthiness
|
3280
|
+
const ptr = page === 0 ? 1 : (page * pageSize);
|
3281
|
+
scope.arrays.set(name, ptr);
|
3282
|
+
}
|
3187
3283
|
|
3188
|
-
|
3189
|
-
} else {
|
3190
|
-
const rawPtr = read_signedLEB128(pointer[0].slice(1));
|
3284
|
+
const pointer = scope.arrays.get(name);
|
3191
3285
|
|
3192
|
-
|
3193
|
-
const firstAssign = !scope.arrays.has(uniqueName);
|
3194
|
-
if (firstAssign) scope.arrays.set(uniqueName, rawPtr);
|
3286
|
+
const local = global ? globals[name] : scope.locals[name];
|
3195
3287
|
|
3196
|
-
|
3197
|
-
|
3198
|
-
if (length !== 0) {
|
3199
|
-
let bytes = compileBytes(length, 'i32');
|
3288
|
+
const useRawElements = !!decl.rawElements;
|
3289
|
+
const elements = useRawElements ? decl.rawElements : decl.elements;
|
3200
3290
|
|
3201
|
-
|
3202
|
-
|
3291
|
+
const valtype = itemTypeToValtype[itemType];
|
3292
|
+
const length = elements.length;
|
3203
3293
|
|
3204
|
-
|
3205
|
-
|
3294
|
+
if (firstAssign && useRawElements && !Prefs.noData) {
|
3295
|
+
// if length is 0 memory/data will just be 0000... anyway
|
3296
|
+
if (length !== 0) {
|
3297
|
+
let bytes = compileBytes(length, 'i32');
|
3206
3298
|
|
3207
|
-
|
3208
|
-
|
3209
|
-
bytes
|
3210
|
-
}) - 1;
|
3299
|
+
if (!initEmpty) for (let i = 0; i < length; i++) {
|
3300
|
+
if (elements[i] == null) continue;
|
3211
3301
|
|
3212
|
-
|
3213
|
-
scope.data.push(ind);
|
3302
|
+
bytes.push(...compileBytes(elements[i], itemType));
|
3214
3303
|
}
|
3215
3304
|
|
3216
|
-
|
3217
|
-
|
3305
|
+
const ind = data.push({
|
3306
|
+
offset: pointer,
|
3307
|
+
bytes
|
3308
|
+
}) - 1;
|
3309
|
+
|
3310
|
+
scope.data ??= [];
|
3311
|
+
scope.data.push(ind);
|
3218
3312
|
}
|
3219
3313
|
|
3220
|
-
|
3221
|
-
|
3222
|
-
if (pointerTmp != null) {
|
3223
|
-
out.push(
|
3224
|
-
[ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
3225
|
-
Opcodes.i32_to_u,
|
3226
|
-
[ Opcodes.local_set, pointerTmp ]
|
3227
|
-
);
|
3314
|
+
// local value as pointer
|
3315
|
+
out.push(...number(pointer));
|
3228
3316
|
|
3229
|
-
|
3230
|
-
}
|
3317
|
+
return [ out, pointer ];
|
3231
3318
|
}
|
3232
3319
|
|
3320
|
+
const pointerTmp = local != null ? localTmp(scope, '#makearray_pointer_tmp', Valtype.i32) : null;
|
3321
|
+
if (pointerTmp != null) {
|
3322
|
+
out.push(
|
3323
|
+
[ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
3324
|
+
Opcodes.i32_to_u,
|
3325
|
+
[ Opcodes.local_set, pointerTmp ]
|
3326
|
+
);
|
3327
|
+
}
|
3328
|
+
|
3329
|
+
const pointerWasm = pointerTmp != null ? [ [ Opcodes.local_get, pointerTmp ] ] : number(pointer, Valtype.i32);
|
3233
3330
|
|
3234
3331
|
// store length
|
3235
3332
|
out.push(
|
3236
|
-
...
|
3333
|
+
...pointerWasm,
|
3237
3334
|
...number(length, Valtype.i32),
|
3238
3335
|
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ]
|
3239
3336
|
);
|
@@ -3245,11 +3342,11 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3245
3342
|
|
3246
3343
|
const offset = ValtypeSize.i32 + i * sizePerEl;
|
3247
3344
|
out.push(
|
3248
|
-
...
|
3345
|
+
...pointerWasm,
|
3249
3346
|
...(useRawElements ? number(elements[i], Valtype[valtype]) : generate(scope, elements[i])),
|
3250
3347
|
[ storeOp, 0, ...unsignedLEB128(offset) ],
|
3251
3348
|
...(!typed ? [] : [ // typed presumes !useRawElements
|
3252
|
-
...
|
3349
|
+
...pointerWasm,
|
3253
3350
|
...getNodeType(scope, elements[i]),
|
3254
3351
|
[ Opcodes.i32_store8, 0, ...unsignedLEB128(offset + ValtypeSize[itemType]) ]
|
3255
3352
|
])
|
@@ -3257,13 +3354,12 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3257
3354
|
}
|
3258
3355
|
|
3259
3356
|
// local value as pointer
|
3260
|
-
out.push(...
|
3261
|
-
if (!intOut) out.push(Opcodes.i32_from_u);
|
3357
|
+
out.push(...pointerWasm, Opcodes.i32_from_u);
|
3262
3358
|
|
3263
3359
|
return [ out, pointer ];
|
3264
3360
|
};
|
3265
3361
|
|
3266
|
-
const storeArray = (scope, array, index, element) => {
|
3362
|
+
const storeArray = (scope, array, index, element, aotPointer = null) => {
|
3267
3363
|
if (!Array.isArray(element)) element = generate(scope, element);
|
3268
3364
|
if (typeof index === 'number') index = number(index);
|
3269
3365
|
|
@@ -3275,25 +3371,26 @@ const storeArray = (scope, array, index, element) => {
|
|
3275
3371
|
Opcodes.i32_to_u,
|
3276
3372
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
3277
3373
|
[ Opcodes.i32_mul ],
|
3278
|
-
|
3279
|
-
|
3280
|
-
|
3281
|
-
|
3374
|
+
...(aotPointer ? [] : [
|
3375
|
+
...array,
|
3376
|
+
Opcodes.i32_to_u,
|
3377
|
+
[ Opcodes.i32_add ],
|
3378
|
+
]),
|
3282
3379
|
[ Opcodes.local_set, offset ],
|
3283
3380
|
|
3284
3381
|
// store value
|
3285
3382
|
[ Opcodes.local_get, offset ],
|
3286
3383
|
...generate(scope, element),
|
3287
|
-
[ Opcodes.store, 0, ValtypeSize.i32 ],
|
3384
|
+
[ Opcodes.store, 0, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ],
|
3288
3385
|
|
3289
3386
|
// store type
|
3290
3387
|
[ Opcodes.local_get, offset ],
|
3291
3388
|
...getNodeType(scope, element),
|
3292
|
-
[ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
3389
|
+
[ Opcodes.i32_store8, 0, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32 + ValtypeSize[valtype]) ]
|
3293
3390
|
];
|
3294
3391
|
};
|
3295
3392
|
|
3296
|
-
const loadArray = (scope, array, index) => {
|
3393
|
+
const loadArray = (scope, array, index, aotPointer = null) => {
|
3297
3394
|
if (typeof index === 'number') index = number(index);
|
3298
3395
|
|
3299
3396
|
const offset = localTmp(scope, '#loadArray_offset', Valtype.i32);
|
@@ -3304,19 +3401,20 @@ const loadArray = (scope, array, index) => {
|
|
3304
3401
|
Opcodes.i32_to_u,
|
3305
3402
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
3306
3403
|
[ Opcodes.i32_mul ],
|
3307
|
-
|
3308
|
-
|
3309
|
-
|
3310
|
-
|
3404
|
+
...(aotPointer ? [] : [
|
3405
|
+
...array,
|
3406
|
+
Opcodes.i32_to_u,
|
3407
|
+
[ Opcodes.i32_add ],
|
3408
|
+
]),
|
3311
3409
|
[ Opcodes.local_set, offset ],
|
3312
3410
|
|
3313
3411
|
// load value
|
3314
3412
|
[ Opcodes.local_get, offset ],
|
3315
|
-
[ Opcodes.load, 0, ValtypeSize.i32 ],
|
3413
|
+
[ Opcodes.load, 0, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ],
|
3316
3414
|
|
3317
3415
|
// load type
|
3318
3416
|
[ Opcodes.local_get, offset ],
|
3319
|
-
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
3417
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32 + ValtypeSize[valtype]) ]
|
3320
3418
|
];
|
3321
3419
|
};
|
3322
3420
|
|
@@ -3348,7 +3446,7 @@ const makeString = (scope, str, global = false, name = '$undeclared', forceBytes
|
|
3348
3446
|
};
|
3349
3447
|
|
3350
3448
|
const generateArray = (scope, decl, global = false, name = '$undeclared', initEmpty = false) => {
|
3351
|
-
return makeArray(scope, decl, global, name, initEmpty, valtype,
|
3449
|
+
return makeArray(scope, decl, global, name, initEmpty, valtype, true)[0];
|
3352
3450
|
};
|
3353
3451
|
|
3354
3452
|
const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
@@ -3367,6 +3465,9 @@ const withType = (scope, wasm, type) => [
|
|
3367
3465
|
|
3368
3466
|
const generateMember = (scope, decl, _global, _name) => {
|
3369
3467
|
const name = decl.object.name;
|
3468
|
+
const pointer = scope.arrays?.get(name);
|
3469
|
+
|
3470
|
+
const aotPointer = Prefs.aotPointerOpt && pointer;
|
3370
3471
|
|
3371
3472
|
// hack: .name
|
3372
3473
|
if (decl.property.name === 'name') {
|
@@ -3407,10 +3508,12 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3407
3508
|
if (Prefs.fastLength) {
|
3408
3509
|
// presume valid length object
|
3409
3510
|
return [
|
3410
|
-
...
|
3411
|
-
|
3511
|
+
...(aotPointer ? number(0, Valtype.i32) : [
|
3512
|
+
...generate(scope, decl.object),
|
3513
|
+
Opcodes.i32_to_u
|
3514
|
+
]),
|
3412
3515
|
|
3413
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3516
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(aotPointer ? pointer : 0) ],
|
3414
3517
|
Opcodes.i32_from_u
|
3415
3518
|
];
|
3416
3519
|
}
|
@@ -3419,10 +3522,12 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3419
3522
|
const known = knownType(scope, type);
|
3420
3523
|
if (known != null) {
|
3421
3524
|
if ([ TYPES.string, TYPES.bytestring, TYPES.array ].includes(known)) return [
|
3422
|
-
...
|
3423
|
-
|
3525
|
+
...(aotPointer ? number(0, Valtype.i32) : [
|
3526
|
+
...generate(scope, decl.object),
|
3527
|
+
Opcodes.i32_to_u
|
3528
|
+
]),
|
3424
3529
|
|
3425
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3530
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(aotPointer ? pointer : 0) ],
|
3426
3531
|
Opcodes.i32_from_u
|
3427
3532
|
];
|
3428
3533
|
|
@@ -3432,10 +3537,12 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3432
3537
|
return [
|
3433
3538
|
...typeIsOneOf(getNodeType(scope, decl.object), [ TYPES.string, TYPES.bytestring, TYPES.array ]),
|
3434
3539
|
[ Opcodes.if, valtypeBinary ],
|
3435
|
-
...
|
3436
|
-
|
3540
|
+
...(aotPointer ? number(0, Valtype.i32) : [
|
3541
|
+
...generate(scope, decl.object),
|
3542
|
+
Opcodes.i32_to_u
|
3543
|
+
]),
|
3437
3544
|
|
3438
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3545
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(aotPointer ? pointer : 0) ],
|
3439
3546
|
Opcodes.i32_from_u,
|
3440
3547
|
|
3441
3548
|
...setLastType(scope, TYPES.number),
|
@@ -3478,29 +3585,25 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3478
3585
|
|
3479
3586
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
3480
3587
|
// hack: this is naughty and will break things!
|
3481
|
-
let newOut = number(0,
|
3588
|
+
let newOut = number(0, valtypeBinary), newPointer = -1;
|
3482
3589
|
if (pages.hasAnyString) {
|
3483
|
-
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
3484
3590
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
3485
|
-
rawElements: new Array(
|
3486
|
-
}, _global, _name, true, 'i16'
|
3591
|
+
rawElements: new Array(1)
|
3592
|
+
}, _global, _name, true, 'i16');
|
3487
3593
|
}
|
3488
3594
|
|
3489
3595
|
return typeSwitch(scope, getNodeType(scope, decl.object), {
|
3490
3596
|
[TYPES.array]: [
|
3491
|
-
...loadArray(scope, object, property),
|
3597
|
+
...loadArray(scope, object, property, aotPointer),
|
3492
3598
|
...setLastType(scope)
|
3493
3599
|
],
|
3600
|
+
|
3494
3601
|
[TYPES.string]: [
|
3495
3602
|
// setup new/out array
|
3496
3603
|
...newOut,
|
3604
|
+
[ Opcodes.drop ],
|
3497
3605
|
|
3498
|
-
//
|
3499
|
-
...number(1, Valtype.i32),
|
3500
|
-
[ Opcodes.i32_store, 0, 0 ],
|
3501
|
-
|
3502
|
-
// use as pointer for store later
|
3503
|
-
...newPointer,
|
3606
|
+
...number(0, Valtype.i32), // base 0 for store later
|
3504
3607
|
|
3505
3608
|
...property,
|
3506
3609
|
Opcodes.i32_to_u,
|
@@ -3508,48 +3611,46 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3508
3611
|
...number(ValtypeSize.i16, Valtype.i32),
|
3509
3612
|
[ Opcodes.i32_mul ],
|
3510
3613
|
|
3511
|
-
...
|
3512
|
-
|
3513
|
-
|
3614
|
+
...(aotPointer ? [] : [
|
3615
|
+
...object,
|
3616
|
+
Opcodes.i32_to_u,
|
3617
|
+
[ Opcodes.i32_add ]
|
3618
|
+
]),
|
3514
3619
|
|
3515
3620
|
// load current string ind {arg}
|
3516
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
3621
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ],
|
3517
3622
|
|
3518
3623
|
// store to new string ind 0
|
3519
|
-
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
3624
|
+
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
|
3520
3625
|
|
3521
3626
|
// return new string (page)
|
3522
|
-
...newPointer,
|
3523
|
-
Opcodes.i32_from_u,
|
3627
|
+
...number(newPointer),
|
3524
3628
|
...setLastType(scope, TYPES.string)
|
3525
3629
|
],
|
3526
3630
|
[TYPES.bytestring]: [
|
3527
3631
|
// setup new/out array
|
3528
3632
|
...newOut,
|
3633
|
+
[ Opcodes.drop ],
|
3529
3634
|
|
3530
|
-
//
|
3531
|
-
...number(1, Valtype.i32),
|
3532
|
-
[ Opcodes.i32_store, 0, 0 ],
|
3533
|
-
|
3534
|
-
// use as pointer for store later
|
3535
|
-
...newPointer,
|
3635
|
+
...number(0, Valtype.i32), // base 0 for store later
|
3536
3636
|
|
3537
3637
|
...property,
|
3538
3638
|
Opcodes.i32_to_u,
|
3539
3639
|
|
3540
|
-
...
|
3541
|
-
|
3542
|
-
|
3640
|
+
...(aotPointer ? [] : [
|
3641
|
+
...object,
|
3642
|
+
Opcodes.i32_to_u,
|
3643
|
+
[ Opcodes.i32_add ]
|
3644
|
+
]),
|
3543
3645
|
|
3544
3646
|
// load current string ind {arg}
|
3545
|
-
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
|
3647
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ],
|
3546
3648
|
|
3547
3649
|
// store to new string ind 0
|
3548
|
-
[ Opcodes.i32_store8, 0, ValtypeSize.i32 ],
|
3650
|
+
[ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
|
3549
3651
|
|
3550
3652
|
// return new string (page)
|
3551
|
-
...newPointer,
|
3552
|
-
Opcodes.i32_from_u,
|
3653
|
+
...number(newPointer),
|
3553
3654
|
...setLastType(scope, TYPES.bytestring)
|
3554
3655
|
],
|
3555
3656
|
|
@@ -3705,13 +3806,12 @@ const internalConstrs = {
|
|
3705
3806
|
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, 'RangeThrow', 'Invalid array length', true);
|
3706
3807
|
|
3707
3808
|
return [
|
3708
|
-
...
|
3809
|
+
...number(0, Valtype.i32),
|
3709
3810
|
...generate(scope, arg, global, name),
|
3710
3811
|
Opcodes.i32_to_u,
|
3711
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1,
|
3812
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(pointer) ],
|
3712
3813
|
|
3713
|
-
...pointer
|
3714
|
-
Opcodes.i32_from_u
|
3814
|
+
...number(pointer)
|
3715
3815
|
];
|
3716
3816
|
},
|
3717
3817
|
type: TYPES.array,
|
@@ -3860,9 +3960,8 @@ const internalConstrs = {
|
|
3860
3960
|
};
|
3861
3961
|
|
3862
3962
|
export default program => {
|
3863
|
-
globals = {
|
3864
|
-
|
3865
|
-
};
|
3963
|
+
globals = {};
|
3964
|
+
globalInd = 0;
|
3866
3965
|
tags = [];
|
3867
3966
|
exceptions = [];
|
3868
3967
|
funcs = [];
|
@@ -3895,7 +3994,6 @@ export default program => {
|
|
3895
3994
|
builtinFuncs = new BuiltinFuncs();
|
3896
3995
|
builtinVars = new BuiltinVars();
|
3897
3996
|
prototypeFuncs = new PrototypeFuncs();
|
3898
|
-
allocator = Allocator(Prefs.allocator ?? 'static');
|
3899
3997
|
|
3900
3998
|
program.id = { name: 'main' };
|
3901
3999
|
|
@@ -3938,8 +4036,6 @@ export default program => {
|
|
3938
4036
|
else main.returns = [];
|
3939
4037
|
}
|
3940
4038
|
|
3941
|
-
delete globals['#ind'];
|
3942
|
-
|
3943
4039
|
// if blank main func and other exports, remove it
|
3944
4040
|
if (main.wasm.length === 0 && funcs.reduce((acc, x) => acc + (x.export ? 1 : 0), 0) > 1) funcs.splice(main.index - importedFuncs.length, 1);
|
3945
4041
|
|