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